From a6c3f6ce1d5bb2d51f2eb85845277e6e7798695c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Oct 2022 10:24:14 +0200 Subject: [PATCH 01/12] CStr: add some doc links --- library/core/src/ffi/c_str.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 55e58c4e0baa5..84ee23ebbdc54 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -13,9 +13,9 @@ use crate::str; /// array of bytes. It can be constructed safely from a &[[u8]] /// slice, or unsafely from a raw `*const c_char`. It can then be /// converted to a Rust &[str] by performing UTF-8 validation, or -/// into an owned `CString`. +/// into an owned [`CString`]. /// -/// `&CStr` is to `CString` as &[str] is to `String`: the former +/// `&CStr` is to [`CString`] as &[str] is to [`String`]: the former /// in each pair are borrowed references; the latter are owned /// strings. /// @@ -24,6 +24,9 @@ use crate::str; /// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide /// a safe interface to other consumers. /// +/// [`CString`]: ../../std/ffi/struct.CString.html +/// [`String`]: ../../std/string/struct.String.html +/// /// # Examples /// /// Inspecting a foreign C string: From 9f28de513a309af7593e8959f92ec11e07ea255f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Oct 2022 20:51:01 +0000 Subject: [PATCH 02/12] Free late-bound lifetimes in closures as well --- compiler/rustc_hir_analysis/src/collect/lifetimes.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index 3f263a6de24ea..3d07f3fbc674d 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -1377,11 +1377,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else if let Some(body_id) = outermost_body { let fn_id = self.tcx.hir().body_owner(body_id); match self.tcx.hir().get(fn_id) { - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) - | Node::TraitItem(&hir::TraitItem { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) + | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { + | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) + | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { let scope = self.tcx.hir().local_def_id(fn_id); def = Region::Free(scope.to_def_id(), def.id().unwrap()); } From 5ba1556e0ddb6805526f8c3938c7aaf266d0b319 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Oct 2022 20:51:15 +0000 Subject: [PATCH 03/12] Create NLL infer vars for late-bound regions from closures --- .../rustc_borrowck/src/universal_regions.rs | 62 +++++++++++-------- compiler/rustc_middle/src/ty/context.rs | 4 +- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 2beb5e0ab5d20..51439dec44091 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -22,7 +22,9 @@ use rustc_hir::{BodyOwnerKind, HirId}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt, +}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; use std::iter; @@ -421,13 +423,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { first_extern_index } else { // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing - // function are actually external regions to us. For example, here, 'a is not local + // function/closures are actually external regions to us. For example, here, 'a is not local // to the closure c (although it is local to the fn foo): // fn foo<'a>() { // let c = || { let x: &'a u32 = ...; } // } - self.infcx - .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); + self.infcx.replace_late_bound_regions_with_nll_infer_vars( + self.infcx.tcx.local_parent(self.mir_def.did), + &mut indices, + ); // Any regions created during the execution of `defining_ty` or during the above // late-bound region replacement are all considered 'extern' regions self.infcx.num_region_vars() @@ -444,12 +448,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { bound_inputs_and_output, &mut indices, ); - // Converse of above, if this is a function then the late-bound regions declared on its - // signature are local to the fn. - if self.mir_def.did.to_def_id() == typeck_root_def_id { - self.infcx - .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); - } + // Converse of above, if this is a function/closure then the late-bound regions declared on its + // signature are local. + self.infcx.replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); let (unnormalized_output_ty, mut unnormalized_input_tys) = inputs_and_output.split_last().unwrap(); @@ -748,18 +749,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { #[instrument(skip(self, indices))] fn replace_late_bound_regions_with_nll_infer_vars( &self, - mir_def_id: LocalDefId, + mut mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, ) { let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id()); - for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| { - debug!(?r); - if !indices.indices.contains_key(&r) { - let region_vid = self.next_nll_region_var(FR); - debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); + + // Walk up the tree, collecting late-bound regions until we hit the typeck root + loop { + for_each_late_bound_region_defined_on(self.tcx, mir_def_id.to_def_id(), |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); + + if mir_def_id.to_def_id() == typeck_root_def_id { + break; + } else { + mir_def_id = self.tcx.parent(mir_def_id.to_def_id()).expect_local(); } - }); + } } } @@ -810,14 +821,11 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { - for ®ion_def_id in late_bounds.iter() { - let name = tcx.item_name(region_def_id.to_def_id()); - let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: fn_def_id, - bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name), - })); - f(liberated_region); - } + for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(fn_def_id.expect_local())) + { + let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; + let liberated_region = + tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, bound_region })); + f(liberated_region); } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3d7e2a0839abc..a9c503585a179 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2895,9 +2895,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_bound_variable_kinds( self.late_bound_vars_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) - .unwrap_or_else(|| { - bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) - }) + .unwrap_or_default() .iter(), ) } From 630dff6ba7217d15e757ba4c552b8a4bedca4130 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Oct 2022 20:51:30 +0000 Subject: [PATCH 04/12] tests --- src/test/ui/closures/binder/late-bound-in-body.rs | 9 +++++++++ src/test/ui/closures/binder/nested-closures.rs | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/closures/binder/late-bound-in-body.rs create mode 100644 src/test/ui/closures/binder/nested-closures.rs diff --git a/src/test/ui/closures/binder/late-bound-in-body.rs b/src/test/ui/closures/binder/late-bound-in-body.rs new file mode 100644 index 0000000000000..bb5c7552fdaa8 --- /dev/null +++ b/src/test/ui/closures/binder/late-bound-in-body.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + let _ = for<'a> || -> () { + let _: &'a bool = &true; + }; +} diff --git a/src/test/ui/closures/binder/nested-closures.rs b/src/test/ui/closures/binder/nested-closures.rs new file mode 100644 index 0000000000000..b3c36e7eebb7a --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures.rs @@ -0,0 +1,7 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} From f27bdf175034bd0455eb960fc0dc8262484f187b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Oct 2022 03:28:05 +0000 Subject: [PATCH 05/12] Collect late-bound regions from all closure parents in `closure_mapping` --- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../rustc_borrowck/src/universal_regions.rs | 82 ++++++++++--------- .../binder/nested-closures-regions.rs | 9 ++ .../binder/nested-closures-regions.stderr | 38 +++++++++ 4 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 src/test/ui/closures/binder/nested-closures-regions.rs create mode 100644 src/test/ui/closures/binder/nested-closures-regions.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8b63294fbab0e..0e7f243bcf36c 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2314,7 +2314,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx tcx, closure_substs, self.num_external_vids, - tcx.typeck_root_def_id(closure_def_id), + closure_def_id.expect_local(), ); debug!("apply_requirements: closure_mapping={:?}", closure_mapping); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 51439dec44091..0f300564c2086 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -243,7 +243,7 @@ impl<'tcx> UniversalRegions<'tcx> { tcx: TyCtxt<'tcx>, closure_substs: SubstsRef<'tcx>, expected_num_vars: usize, - typeck_root_def_id: DefId, + closure_def_id: LocalDefId, ) -> IndexVec> { let mut region_mapping = IndexVec::with_capacity(expected_num_vars); region_mapping.push(tcx.lifetimes.re_static); @@ -251,9 +251,13 @@ impl<'tcx> UniversalRegions<'tcx> { region_mapping.push(fr); }); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - region_mapping.push(r); - }); + for_each_late_bound_region_in_scope( + tcx, + tcx.local_parent(closure_def_id), + |r| { + region_mapping.push(r); + }, + ); assert_eq!( region_mapping.len(), @@ -341,9 +345,8 @@ impl<'tcx> UniversalRegions<'tcx> { // tests, and the resulting print-outs include def-ids // and other things that are not stable across tests! // So we just include the region-vid. Annoying. - let typeck_root_def_id = tcx.typeck_root_def_id(def_id); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),)); + for_each_late_bound_region_in_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::Generator(def_id, substs, _) => { @@ -356,9 +359,8 @@ impl<'tcx> UniversalRegions<'tcx> { // FIXME: As above, we'd like to print out the region // `r` but doing so is not stable across architectures // and so forth. - let typeck_root_def_id = tcx.typeck_root_def_id(def_id); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),)); + for_each_late_bound_region_in_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::FnDef(def_id, substs) => { @@ -749,28 +751,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { #[instrument(skip(self, indices))] fn replace_late_bound_regions_with_nll_infer_vars( &self, - mut mir_def_id: LocalDefId, + mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, ) { - let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id()); - - // Walk up the tree, collecting late-bound regions until we hit the typeck root - loop { - for_each_late_bound_region_defined_on(self.tcx, mir_def_id.to_def_id(), |r| { - debug!(?r); - if !indices.indices.contains_key(&r) { - let region_vid = self.next_nll_region_var(FR); - debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.to_region_vid()); - } - }); - - if mir_def_id.to_def_id() == typeck_root_def_id { - break; - } else { - mir_def_id = self.tcx.parent(mir_def_id.to_def_id()).expect_local(); + for_each_late_bound_region_in_scope(self.tcx, mir_def_id, |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); } - } + }); } } @@ -814,18 +805,31 @@ impl<'tcx> UniversalRegionIndices<'tcx> { } } -/// Iterates over the late-bound regions defined on fn_def_id and -/// invokes `f` with the liberated form of each one. -fn for_each_late_bound_region_defined_on<'tcx>( +/// Iterates over the late-bound regions defined on fn_def_id and all of its +/// parents, up to the typeck root, and invokes `f` with the liberated form +/// of each one. +fn for_each_late_bound_region_in_scope<'tcx>( tcx: TyCtxt<'tcx>, - fn_def_id: DefId, + mut mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(fn_def_id.expect_local())) - { - let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; - let liberated_region = - tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, bound_region })); - f(liberated_region); + let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id()); + + // Walk up the tree, collecting late-bound regions until we hit the typeck root + loop { + for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { + let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; + let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { + scope: mir_def_id.to_def_id(), + bound_region, + })); + f(liberated_region); + } + + if mir_def_id.to_def_id() == typeck_root_def_id { + break; + } else { + mir_def_id = tcx.local_parent(mir_def_id); + } } } diff --git a/src/test/ui/closures/binder/nested-closures-regions.rs b/src/test/ui/closures/binder/nested-closures-regions.rs new file mode 100644 index 0000000000000..6bfc6c80b7882 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] +#![feature(rustc_attrs)] + +#[rustc_regions] +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/src/test/ui/closures/binder/nested-closures-regions.stderr b/src/test/ui/closures/binder/nested-closures-regions.stderr new file mode 100644 index 0000000000000..b385e0ed6e0a5 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.stderr @@ -0,0 +1,38 @@ +note: external requirements + --> $DIR/nested-closures-regions.rs:8:24 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0}::{closure#0} with closure substs [ + i8, + extern "rust-call" fn((&(),)), + (), + ] + = note: late-bound region is '_#4r + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + = note: where '_#2r: '_#1r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:8:5 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0} with closure substs [ + i8, + extern "rust-call" fn(()), + (), + ] + = note: late-bound region is '_#2r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:7:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = note: defining type: main + From 4427af082797a1e477781efd09947bb27d9b19c3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Oct 2022 21:18:17 +0000 Subject: [PATCH 06/12] Make external/local late-bound region registration more explicit --- .../rustc_borrowck/src/universal_regions.rs | 93 ++++++++++++++----- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 0f300564c2086..482e10d520b76 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -251,13 +251,9 @@ impl<'tcx> UniversalRegions<'tcx> { region_mapping.push(fr); }); - for_each_late_bound_region_in_scope( - tcx, - tcx.local_parent(closure_def_id), - |r| { - region_mapping.push(r); - }, - ); + for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| { + region_mapping.push(r); + }); assert_eq!( region_mapping.len(), @@ -345,7 +341,7 @@ impl<'tcx> UniversalRegions<'tcx> { // tests, and the resulting print-outs include def-ids // and other things that are not stable across tests! // So we just include the region-vid. Annoying. - for_each_late_bound_region_in_scope(tcx, def_id.expect_local(), |r| { + for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| { err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } @@ -359,7 +355,7 @@ impl<'tcx> UniversalRegions<'tcx> { // FIXME: As above, we'd like to print out the region // `r` but doing so is not stable across architectures // and so forth. - for_each_late_bound_region_in_scope(tcx, def_id.expect_local(), |r| { + for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| { err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } @@ -430,10 +426,19 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // fn foo<'a>() { // let c = || { let x: &'a u32 = ...; } // } - self.infcx.replace_late_bound_regions_with_nll_infer_vars( + for_each_late_bound_region_in_recursive_scope( + self.infcx.tcx, self.infcx.tcx.local_parent(self.mir_def.did), - &mut indices, + |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.infcx.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }, ); + // Any regions created during the execution of `defining_ty` or during the above // late-bound region replacement are all considered 'extern' regions self.infcx.num_region_vars() @@ -452,7 +457,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ); // Converse of above, if this is a function/closure then the late-bound regions declared on its // signature are local. - self.infcx.replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices); + for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.infcx.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); let (unnormalized_output_ty, mut unnormalized_input_tys) = inputs_and_output.split_last().unwrap(); @@ -695,7 +707,13 @@ trait InferCtxtExt<'tcx> { where T: TypeFoldable<'tcx>; - fn replace_late_bound_regions_with_nll_infer_vars( + fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( + &self, + mir_def_id: LocalDefId, + indices: &mut UniversalRegionIndices<'tcx>, + ); + + fn replace_late_bound_regions_with_nll_infer_vars_in_item( &self, mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, @@ -749,12 +767,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// set of late-bound regions and checks for any that we have not yet seen, adding them to the /// inputs vector. #[instrument(skip(self, indices))] - fn replace_late_bound_regions_with_nll_infer_vars( + fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( &self, mir_def_id: LocalDefId, indices: &mut UniversalRegionIndices<'tcx>, ) { - for_each_late_bound_region_in_scope(self.tcx, mir_def_id, |r| { + for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let region_vid = self.next_nll_region_var(FR); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); + } + + #[instrument(skip(self, indices))] + fn replace_late_bound_regions_with_nll_infer_vars_in_item( + &self, + mir_def_id: LocalDefId, + indices: &mut UniversalRegionIndices<'tcx>, + ) { + for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| { debug!(?r); if !indices.indices.contains_key(&r) { let region_vid = self.next_nll_region_var(FR); @@ -805,10 +839,10 @@ impl<'tcx> UniversalRegionIndices<'tcx> { } } -/// Iterates over the late-bound regions defined on fn_def_id and all of its +/// Iterates over the late-bound regions defined on `mir_def_id` and all of its /// parents, up to the typeck root, and invokes `f` with the liberated form /// of each one. -fn for_each_late_bound_region_in_scope<'tcx>( +fn for_each_late_bound_region_in_recursive_scope<'tcx>( tcx: TyCtxt<'tcx>, mut mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), @@ -817,14 +851,7 @@ fn for_each_late_bound_region_in_scope<'tcx>( // Walk up the tree, collecting late-bound regions until we hit the typeck root loop { - for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { - let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; - let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: mir_def_id.to_def_id(), - bound_region, - })); - f(liberated_region); - } + for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f); if mir_def_id.to_def_id() == typeck_root_def_id { break; @@ -833,3 +860,19 @@ fn for_each_late_bound_region_in_scope<'tcx>( } } } + +/// Iterates over the late-bound regions defined on `mir_def_id` and all of its +/// parents, up to the typeck root, and invokes `f` with the liberated form +/// of each one. +fn for_each_late_bound_region_in_item<'tcx>( + tcx: TyCtxt<'tcx>, + mir_def_id: LocalDefId, + mut f: impl FnMut(ty::Region<'tcx>), +) { + for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { + let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; + let liberated_region = tcx + .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region })); + f(liberated_region); + } +} From 2768c2fb257fccc692712d5f38d979f4a8f127dd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Oct 2022 21:24:39 +0000 Subject: [PATCH 07/12] Add bug! back to late_bound_vars query --- compiler/rustc_borrowck/src/universal_regions.rs | 4 ++++ compiler/rustc_middle/src/ty/context.rs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 482e10d520b76..618da9e325325 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -869,6 +869,10 @@ fn for_each_late_bound_region_in_item<'tcx>( mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), ) { + if !tcx.def_kind(mir_def_id).is_fn_like() { + return; + } + for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; let liberated_region = tcx diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a9c503585a179..3d7e2a0839abc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2895,7 +2895,9 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_bound_variable_kinds( self.late_bound_vars_map(id.owner) .and_then(|map| map.get(&id.local_id).cloned()) - .unwrap_or_default() + .unwrap_or_else(|| { + bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) + }) .iter(), ) } From 10a5e75537e3189ffa808be7eadc19569966b266 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Tue, 1 Nov 2022 12:24:51 -0500 Subject: [PATCH 08/12] Add track_caller to some Lock methods --- compiler/rustc_data_structures/src/sync.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 9c0fb8265cff7..c550f246e094a 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -410,6 +410,7 @@ impl Lock { #[cfg(parallel_compiler)] #[inline(always)] + #[track_caller] pub fn lock(&self) -> LockGuard<'_, T> { if ERROR_CHECKING { self.0.try_lock().expect("lock was already held") @@ -420,21 +421,25 @@ impl Lock { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn lock(&self) -> LockGuard<'_, T> { self.0.borrow_mut() } #[inline(always)] + #[track_caller] pub fn with_lock R, R>(&self, f: F) -> R { f(&mut *self.lock()) } #[inline(always)] + #[track_caller] pub fn borrow(&self) -> LockGuard<'_, T> { self.lock() } #[inline(always)] + #[track_caller] pub fn borrow_mut(&self) -> LockGuard<'_, T> { self.lock() } @@ -476,6 +481,7 @@ impl RwLock { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn read(&self) -> ReadGuard<'_, T> { self.0.borrow() } @@ -491,6 +497,7 @@ impl RwLock { } #[inline(always)] + #[track_caller] pub fn with_read_lock R, R>(&self, f: F) -> R { f(&*self.read()) } @@ -509,6 +516,7 @@ impl RwLock { #[cfg(not(parallel_compiler))] #[inline(always)] + #[track_caller] pub fn write(&self) -> WriteGuard<'_, T> { self.0.borrow_mut() } @@ -524,16 +532,19 @@ impl RwLock { } #[inline(always)] + #[track_caller] pub fn with_write_lock R, R>(&self, f: F) -> R { f(&mut *self.write()) } #[inline(always)] + #[track_caller] pub fn borrow(&self) -> ReadGuard<'_, T> { self.read() } #[inline(always)] + #[track_caller] pub fn borrow_mut(&self) -> WriteGuard<'_, T> { self.write() } From df326946ed5668bf05c37ece50e271b1c9fbdf1e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Nov 2022 18:15:24 +0100 Subject: [PATCH 09/12] Remove rustdoc clean::Visibility type --- src/librustdoc/clean/inline.rs | 5 +- src/librustdoc/clean/mod.rs | 9 +- src/librustdoc/clean/types.rs | 40 ++---- src/librustdoc/clean/utils.rs | 9 +- src/librustdoc/html/format.rs | 151 +++++++++++------------ src/librustdoc/html/render/mod.rs | 8 +- src/librustdoc/html/render/print_item.rs | 41 +++--- src/librustdoc/json/conversions.rs | 11 +- src/librustdoc/passes/stripper.rs | 8 +- 9 files changed, 129 insertions(+), 153 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ec93eefb7d1ee..841c4f9d53005 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -19,8 +19,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, - clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt, - ImplKind, ItemId, Type, + clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -654,7 +653,7 @@ fn build_macro( match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) { LoadedMacro::MacroDef(item_def, _) => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = clean_visibility(cx.tcx.visibility(import_def_id.unwrap_or(def_id))); + let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source(cx, name, def, def_id, vis), }) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ad4ad4104e104..77cb7196cde34 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1799,13 +1799,6 @@ pub(crate) fn clean_field_with_def_id( Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx) } -pub(crate) fn clean_visibility(vis: ty::Visibility) -> Visibility { - match vis { - ty::Visibility::Public => Visibility::Public, - ty::Visibility::Restricted(module) => Visibility::Restricted(module), - } -} - pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item { let kind = match variant.ctor_kind { CtorKind::Const => Variant::CLike(match variant.discr { @@ -1962,7 +1955,7 @@ fn clean_maybe_renamed_item<'tcx>( clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } ItemKind::Macro(ref macro_def, _) => { - let ty_vis = clean_visibility(cx.tcx.visibility(def_id)); + let ty_vis = cx.tcx.visibility(def_id); MacroItem(Macro { source: display_macro_source(cx, name, macro_def, def_id, ty_vis), }) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 439311f064029..8b265dda90c03 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -24,7 +24,7 @@ use rustc_hir::{BodyId, Mutability}; use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; use rustc_index::vec::IndexVec; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, DefIdTree, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility}; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DUMMY_SP; @@ -34,7 +34,6 @@ use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use crate::clean::cfg::Cfg; -use crate::clean::clean_visibility; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; @@ -51,7 +50,6 @@ pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, Slice, Tuple, }; -pub(crate) use self::Visibility::{Inherited, Public}; #[cfg(test)] mod tests; @@ -706,26 +704,28 @@ impl Item { Some(header) } - pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility { + /// Returns the visibility of the current item. If the visibility is "inherited", then `None` + /// is returned. + pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option> { let def_id = match self.item_id { // Anything but DefId *shouldn't* matter, but return a reasonable value anyway. - ItemId::Auto { .. } | ItemId::Blanket { .. } => return Visibility::Inherited, + ItemId::Auto { .. } | ItemId::Blanket { .. } => return None, // Primitives and Keywords are written in the source code as private modules. // The modules need to be private so that nobody actually uses them, but the // keywords and primitives that they are documenting are public. - ItemId::Primitive(..) => return Visibility::Public, + ItemId::Primitive(..) => return Some(Visibility::Public), ItemId::DefId(def_id) => def_id, }; match *self.kind { // Explication on `ItemId::Primitive` just above. - ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Visibility::Public, + ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public), // Variant fields inherit their enum's visibility. StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => { - return Visibility::Inherited; + return None; } // Variants always inherit visibility - VariantItem(..) => return Visibility::Inherited, + VariantItem(..) => return None, // Trait items inherit the trait's visibility AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..) | TyMethodItem(..) | MethodItem(..) => { @@ -739,7 +739,7 @@ impl Item { } }; if is_trait_item { - return Visibility::Inherited; + return None; } } _ => {} @@ -748,7 +748,7 @@ impl Item { Some(inlined) => inlined, None => def_id, }; - clean_visibility(tcx.visibility(def_id)) + Some(tcx.visibility(def_id)) } } @@ -2078,24 +2078,6 @@ impl From for PrimitiveType { } } -#[derive(Copy, Clone, Debug)] -pub(crate) enum Visibility { - /// `pub` - Public, - /// Visibility inherited from parent. - /// - /// For example, this is the visibility of private items and of enum variants. - Inherited, - /// `pub(crate)`, `pub(super)`, or `pub(in path::to::somewhere)` - Restricted(DefId), -} - -impl Visibility { - pub(crate) fn is_public(&self) -> bool { - matches!(self, Visibility::Public) - } -} - #[derive(Clone, Debug)] pub(crate) struct Struct { pub(crate) struct_type: CtorKind, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 518e320235ff1..df20dc3fc3f7e 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -4,9 +4,10 @@ use crate::clean::render_macro_matchers::render_macro_matcher; use crate::clean::{ clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, - PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility, + PathSegment, Primitive, PrimitiveType, Type, TypeBinding, }; use crate::core::DocContext; +use crate::html::format::visibility_to_src_with_space; use rustc_ast as ast; use rustc_ast::tokenstream::TokenTree; @@ -583,7 +584,7 @@ pub(super) fn display_macro_source( name: Symbol, def: &ast::MacroDef, def_id: DefId, - vis: Visibility, + vis: ty::Visibility, ) -> String { let tts: Vec<_> = def.body.inner_tokens().into_trees().collect(); // Extract the spans of all matchers. They represent the "interface" of the macro. @@ -595,14 +596,14 @@ pub(super) fn display_macro_source( if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", - vis.to_src_with_space(cx.tcx, def_id), + visibility_to_src_with_space(Some(vis), cx.tcx, def_id), name, matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::(), ) } else { format!( "{}macro {} {{\n{}}}", - vis.to_src_with_space(cx.tcx, def_id), + visibility_to_src_with_space(Some(vis), cx.tcx, def_id), name, render_macro_arms(cx.tcx, matchers, ","), ) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 37202f786ed80..06db3fb0ec400 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1420,87 +1420,84 @@ impl clean::FnDecl { } } -impl clean::Visibility { - pub(crate) fn print_with_space<'a, 'tcx: 'a>( - self, - item_did: ItemId, - cx: &'a Context<'tcx>, - ) -> impl fmt::Display + 'a + Captures<'tcx> { - use std::fmt::Write as _; - - let to_print: Cow<'static, str> = match self { - clean::Public => "pub ".into(), - clean::Inherited => "".into(), - clean::Visibility::Restricted(vis_did) => { - // FIXME(camelid): This may not work correctly if `item_did` is a module. - // However, rustdoc currently never displays a module's - // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id()); - - if vis_did.is_crate_root() { - "pub(crate) ".into() - } else if parent_module == Some(vis_did) { - // `pub(in foo)` where `foo` is the parent module - // is the same as no visibility modifier - "".into() - } else if parent_module - .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) - == Some(vis_did) - { - "pub(super) ".into() - } else { - let path = cx.tcx().def_path(vis_did); - debug!("path={:?}", path); - // modified from `resolved_path()` to work with `DefPathData` - let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); - let anchor = anchor(vis_did, last_name, cx).to_string(); - - let mut s = "pub(in ".to_owned(); - for seg in &path.data[..path.data.len() - 1] { - let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); - } - let _ = write!(s, "{}) ", anchor); - s.into() +pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( + visibility: Option>, + item_did: ItemId, + cx: &'a Context<'tcx>, +) -> impl fmt::Display + 'a + Captures<'tcx> { + use std::fmt::Write as _; + + let to_print: Cow<'static, str> = match visibility { + None => "".into(), + Some(ty::Visibility::Public) => "pub ".into(), + Some(ty::Visibility::Restricted(vis_did)) => { + // FIXME(camelid): This may not work correctly if `item_did` is a module. + // However, rustdoc currently never displays a module's + // visibility, so it shouldn't matter. + let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id()); + + if vis_did.is_crate_root() { + "pub(crate) ".into() + } else if parent_module == Some(vis_did) { + // `pub(in foo)` where `foo` is the parent module + // is the same as no visibility modifier + "".into() + } else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent)) + == Some(vis_did) + { + "pub(super) ".into() + } else { + let path = cx.tcx().def_path(vis_did); + debug!("path={:?}", path); + // modified from `resolved_path()` to work with `DefPathData` + let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); + let anchor = anchor(vis_did, last_name, cx).to_string(); + + let mut s = "pub(in ".to_owned(); + for seg in &path.data[..path.data.len() - 1] { + let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap()); } + let _ = write!(s, "{}) ", anchor); + s.into() } - }; - display_fn(move |f| write!(f, "{}", to_print)) - } + } + }; + display_fn(move |f| write!(f, "{}", to_print)) +} - /// This function is the same as print_with_space, except that it renders no links. - /// It's used for macros' rendered source view, which is syntax highlighted and cannot have - /// any HTML in it. - pub(crate) fn to_src_with_space<'a, 'tcx: 'a>( - self, - tcx: TyCtxt<'tcx>, - item_did: DefId, - ) -> impl fmt::Display + 'a + Captures<'tcx> { - let to_print = match self { - clean::Public => "pub ".to_owned(), - clean::Inherited => String::new(), - clean::Visibility::Restricted(vis_did) => { - // FIXME(camelid): This may not work correctly if `item_did` is a module. - // However, rustdoc currently never displays a module's - // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(tcx, item_did); - - if vis_did.is_crate_root() { - "pub(crate) ".to_owned() - } else if parent_module == Some(vis_did) { - // `pub(in foo)` where `foo` is the parent module - // is the same as no visibility modifier - String::new() - } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent)) - == Some(vis_did) - { - "pub(super) ".to_owned() - } else { - format!("pub(in {}) ", tcx.def_path_str(vis_did)) - } +/// This function is the same as print_with_space, except that it renders no links. +/// It's used for macros' rendered source view, which is syntax highlighted and cannot have +/// any HTML in it. +pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>( + visibility: Option>, + tcx: TyCtxt<'tcx>, + item_did: DefId, +) -> impl fmt::Display + 'a + Captures<'tcx> { + let to_print = match visibility { + None => String::new(), + Some(ty::Visibility::Public) => "pub ".to_owned(), + Some(ty::Visibility::Restricted(vis_did)) => { + // FIXME(camelid): This may not work correctly if `item_did` is a module. + // However, rustdoc currently never displays a module's + // visibility, so it shouldn't matter. + let parent_module = find_nearest_parent_module(tcx, item_did); + + if vis_did.is_crate_root() { + "pub(crate) ".to_owned() + } else if parent_module == Some(vis_did) { + // `pub(in foo)` where `foo` is the parent module + // is the same as no visibility modifier + String::new() + } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent)) + == Some(vis_did) + { + "pub(super) ".to_owned() + } else { + format!("pub(in {}) ", tcx.def_path_str(vis_did)) } - }; - display_fn(move |f| f.write_str(&to_print)) - } + } + }; + display_fn(move |f| f.write_str(&to_print)) } pub(crate) trait PrintWithSpace { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index adf501a024031..3a041ae15d618 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -70,8 +70,8 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ href, join_with_double_colon, print_abi_with_space, print_constness_with_space, - print_default_space, print_generic_bounds, print_where_clause, Buffer, Ending, HrefError, - PrintWithSpace, + print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space, + Buffer, Ending, HrefError, PrintWithSpace, }; use crate::html::highlight; use crate::html::markdown::{ @@ -752,7 +752,7 @@ fn assoc_const( w, "{extra}{vis}const {name}: {ty}", extra = extra, - vis = it.visibility(tcx).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), href = assoc_href_attr(it, link, cx), name = it.name.as_ref().unwrap(), ty = ty.print(cx), @@ -809,7 +809,7 @@ fn assoc_method( let tcx = cx.tcx(); let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item"); let name = meth.name.as_ref().unwrap(); - let vis = meth.visibility(tcx).print_with_space(meth.item_id, cx).to_string(); + let vis = visibility_print_with_space(meth.visibility(tcx), meth.item_id, cx).to_string(); // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove // this condition. let constness = match render_mode { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 13df08280b5a8..3225ddabe2e75 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::stability; use rustc_middle::span_bug; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{Adt, TyCtxt}; +use rustc_middle::ty::{self, Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; @@ -28,7 +28,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, - Buffer, Ending, PrintWithSpace, + visibility_print_with_space, Buffer, Ending, PrintWithSpace, }; use crate::html::highlight; use crate::html::layout::Page; @@ -328,14 +328,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: Some(src) => write!( w, "
{}extern crate {} as {};", - myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), anchor(myitem.item_id.expect_def_id(), src, cx), myitem.name.unwrap(), ), None => write!( w, "
{}extern crate {};", - myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx), ), } @@ -385,7 +385,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
\ {stab_tags_before}{stab_tags}{stab_tags_after}", stab = stab.unwrap_or_default(), - vis = myitem.visibility(tcx).print_with_space(myitem.item_id, cx), + vis = visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx), imp = import.print(cx), ); w.write_str(ITEM_TABLE_ROW_CLOSE); @@ -410,7 +410,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: let add = if stab.is_some() { " " } else { "" }; let visibility_emoji = match myitem.visibility(tcx) { - clean::Visibility::Restricted(_) => { + Some(ty::Visibility::Restricted(_)) => { " ðŸ”’ " } _ => "", @@ -503,7 +503,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle let unsafety = header.unsafety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let asyncness = header.asyncness.print_with_space(); - let visibility = it.visibility(tcx).print_with_space(it.item_id, cx).to_string(); + let visibility = visibility_print_with_space(it.visibility(tcx), it.item_id, cx).to_string(); let name = it.name.unwrap(); let generics_len = format!("{:#}", f.generics.print(cx)).len(); @@ -561,7 +561,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: write!( w, "{}{}{}trait {}{}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), t.unsafety(tcx).print_with_space(), if t.is_auto(tcx) { "auto " } else { "" }, it.name.unwrap(), @@ -1086,7 +1086,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { wrap_item(w, "typedef", |w| { render_attributes_in_pre(w, it, ""); - write!(w, "{}", it.visibility(cx.tcx()).print_with_space(it.item_id, cx)); + write!(w, "{}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx)); write!( w, "type {}{}{where_clause} = {type_};", @@ -1183,7 +1183,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!( w, "{}enum {}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), it.name.unwrap(), e.generics.print(cx), ); @@ -1398,7 +1398,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle write!( w, "{vis}const {name}: {typ}", - vis = it.visibility(tcx).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), name = it.name.unwrap(), typ = c.type_.print(cx), ); @@ -1499,7 +1499,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean write!( w, "{vis}static {mutability}{name}: {typ}", - vis = it.visibility(cx.tcx()).print_with_space(it.item_id, cx), + vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), mutability = s.mutability.print_with_space(), name = it.name.unwrap(), typ = s.type_.print(cx) @@ -1517,7 +1517,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { write!( w, " {}type {};\n}}", - it.visibility(cx.tcx()).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), it.name.unwrap(), ); }); @@ -1671,7 +1671,12 @@ fn render_union( cx: &Context<'_>, ) { let tcx = cx.tcx(); - write!(w, "{}union {}", it.visibility(tcx).print_with_space(it.item_id, cx), it.name.unwrap(),); + write!( + w, + "{}union {}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + it.name.unwrap(), + ); let where_displayed = g .map(|g| { @@ -1698,7 +1703,7 @@ fn render_union( write!( w, " {}{}: {},\n{}", - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), field.name.unwrap(), ty.print(cx), tab @@ -1729,7 +1734,7 @@ fn render_struct( write!( w, "{}{}{}", - it.visibility(tcx).print_with_space(it.item_id, cx), + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), if structhead { "struct " } else { "" }, it.name.unwrap() ); @@ -1759,7 +1764,7 @@ fn render_struct( w, "\n{} {}{}: {},", tab, - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), field.name.unwrap(), ty.print(cx), ); @@ -1791,7 +1796,7 @@ fn render_struct( write!( w, "{}{}", - field.visibility(tcx).print_with_space(field.item_id, cx), + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), ty.print(cx), ) } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4962eb8f8e176..62ae9519e4b05 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -100,13 +100,12 @@ impl JsonRenderer<'_> { } } - fn convert_visibility(&self, v: clean::Visibility) -> Visibility { - use clean::Visibility::*; + fn convert_visibility(&self, v: Option>) -> Visibility { match v { - Public => Visibility::Public, - Inherited => Visibility::Default, - Restricted(did) if did.is_crate_root() => Visibility::Crate, - Restricted(did) => Visibility::Restricted { + None => Visibility::Default, + Some(ty::Visibility::Public) => Visibility::Public, + Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, + Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { parent: from_item_id(did.into(), self.tcx), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index b2047360ccd9a..995fb5dcc1c86 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -1,6 +1,6 @@ //! A collection of utility functions for the `strip_*` passes. use rustc_hir::def_id::DefId; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_span::symbol::sym; use std::mem; @@ -81,13 +81,13 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } clean::StructFieldItem(..) => { - if !i.visibility(self.tcx).is_public() { + if i.visibility(self.tcx) != Some(Visibility::Public) { return Some(strip_item(i)); } } clean::ModuleItem(..) => { - if i.item_id.is_local() && !i.visibility(self.tcx).is_public() { + if i.item_id.is_local() && i.visibility(self.tcx) != Some(Visibility::Public) { debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = strip_item(self.fold_item_recur(i)); @@ -246,7 +246,7 @@ impl<'tcx> DocFolder for ImportStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { match *i.kind { clean::ExternCrateItem { .. } | clean::ImportItem(..) - if !i.visibility(self.tcx).is_public() => + if i.visibility(self.tcx) != Some(Visibility::Public) => { None } From f65cb6868ddf7258bd153f2d02906c10abbb1a90 Mon Sep 17 00:00:00 2001 From: Douwe Schulte Date: Thu, 3 Nov 2022 21:19:02 +0000 Subject: [PATCH 10/12] Fixed typos Fixed a typo that has been found on two locations in comments. --- library/alloc/src/vec/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index bbbdc3aa2a2d3..834c8f58cb2a9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2588,7 +2588,7 @@ impl ExtendFromWithinSpec for Vec { let (this, spare, len) = unsafe { self.split_at_spare_mut_with_len() }; // SAFETY: - // - caller guaratees that src is a valid index + // - caller guarantees that src is a valid index let to_clone = unsafe { this.get_unchecked(src) }; iter::zip(to_clone, spare) @@ -2607,7 +2607,7 @@ impl ExtendFromWithinSpec for Vec { let (init, spare) = self.split_at_spare_mut(); // SAFETY: - // - caller guaratees that `src` is a valid index + // - caller guarantees that `src` is a valid index let source = unsafe { init.get_unchecked(src) }; // SAFETY: From 1013ee8df512015855937615500690664399545f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 4 Nov 2022 03:08:28 +0000 Subject: [PATCH 11/12] Fix ICE when negative impl is collected during eager mono --- compiler/rustc_monomorphize/src/collector.rs | 4 ++++ src/test/ui/traits/negative-impls/eager-mono.rs | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/traits/negative-impls/eager-mono.rs diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3cfddd75462c0..58ddb807059ae 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1336,6 +1336,10 @@ fn create_mono_items_for_default_impls<'tcx>( ) { match item.kind { hir::ItemKind::Impl(ref impl_) => { + if matches!(impl_.polarity, hir::ImplPolarity::Negative(_)) { + return; + } + for param in impl_.generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} diff --git a/src/test/ui/traits/negative-impls/eager-mono.rs b/src/test/ui/traits/negative-impls/eager-mono.rs new file mode 100644 index 0000000000000..ce770376c0b2f --- /dev/null +++ b/src/test/ui/traits/negative-impls/eager-mono.rs @@ -0,0 +1,12 @@ +// build-pass +// compile-flags:-C link-dead-code=y + +#![feature(negative_impls)] + +trait Foo { + fn foo() {} +} + +impl !Foo for () {} + +fn main() {} From 97ddc6343afd1f3f916d57a5c0e8fc4467c760da Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 4 Nov 2022 13:59:04 +0900 Subject: [PATCH 12/12] remove unused argument from `throw_unresolved_import_error` --- compiler/rustc_resolve/src/imports.rs | 28 ++++++++++----------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f2cc50c199fc8..44965dd6db84f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -450,7 +450,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { { // In the case of a new import line, throw a diagnostic message // for the previous line. - self.throw_unresolved_import_error(errors, None); + self.throw_unresolved_import_error(errors); errors = vec![]; } if seen_spans.insert(err.span) { @@ -482,29 +482,21 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } if !errors.is_empty() { - self.throw_unresolved_import_error(errors, None); + self.throw_unresolved_import_error(errors); } } - fn throw_unresolved_import_error( - &self, - errors: Vec<(String, UnresolvedImportError)>, - span: Option, - ) { + fn throw_unresolved_import_error(&self, errors: Vec<(String, UnresolvedImportError)>) { + if errors.is_empty() { + return; + } + /// Upper limit on the number of `span_label` messages. const MAX_LABEL_COUNT: usize = 10; - let (span, msg) = if errors.is_empty() { - (span.unwrap(), "unresolved import".to_string()) - } else { - let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect()); - - let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::>(); - - let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); - - (span, msg) - }; + let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect()); + let paths = errors.iter().map(|(path, _)| format!("`{}`", path)).collect::>(); + let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),); let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg);