diff options
| author | bors <bors@rust-lang.org> | 2021-02-23 17:24:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-02-23 17:24:33 +0000 |
| commit | fe1bf8e05c39bdcc73fc09e246b7209444e389bc (patch) | |
| tree | 9265dd81347434a5b0b6785222fa0b5901e43a1e /src | |
| parent | 019610754363d1d92a8d0f364d2c0909d6f53dfd (diff) | |
| parent | 51511c75b558beddab7fb4b6d8277a872714b87a (diff) | |
| download | rust-fe1bf8e05c39bdcc73fc09e246b7209444e389bc.tar.gz rust-fe1bf8e05c39bdcc73fc09e246b7209444e389bc.zip | |
Auto merge of #82443 - Dylan-DPC:rollup-yni7uio, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #81629 (Point out implicit deref coercions in borrow) - #82113 (Improve non_fmt_panic lint.) - #82258 (Implement -Z hir-stats for nested foreign items) - #82296 (Support `pub` on `macro_rules`) - #82297 (Consider auto derefs before warning about write only fields) - #82305 (Remove many RefCells from DocContext) - #82308 (Lower condition of `if` expression before it's "then" block) - #82311 (Jsondocck improvements) - #82362 (Fix mir-cfg dumps) - #82391 (disable atomic_max/min tests in Miri) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'src')
53 files changed, 998 insertions, 116 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 711b0298565..a24cb0a0f93 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ) -> Option<Item> { let tcx = self.cx.tcx; let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }; - if !self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)) { + if !self.cx.generated_synthetics.insert((ty, trait_def_id)) { debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); return None; } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index a9d19a725c4..94b82037e75 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -22,8 +22,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { debug!("get_blanket_impls({:?})", ty); let mut impls = Vec::new(); for &trait_def_id in self.cx.tcx.all_traits(LOCAL_CRATE).iter() { - if !self.cx.renderinfo.borrow().access_levels.is_public(trait_def_id) - || self.cx.generated_synthetics.borrow_mut().get(&(ty, trait_def_id)).is_some() + if !self.cx.renderinfo.access_levels.is_public(trait_def_id) + || self.cx.generated_synthetics.get(&(ty, trait_def_id)).is_some() { continue; } @@ -94,7 +94,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { return; } - self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)); + self.cx.generated_synthetics.insert((ty, trait_def_id)); let provided_trait_methods = self .cx .tcx diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index fded0499ba6..ea75d1614bd 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -122,7 +122,7 @@ crate fn try_inline( let target_attrs = load_attrs(cx, did); let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone); - cx.renderinfo.borrow_mut().inlined.insert(did); + cx.renderinfo.inlined.insert(did); let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx); ret.push(clean::Item { attrs, ..what_rustc_thinks }); Some(ret) @@ -156,7 +156,7 @@ crate fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> { /// /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. -crate fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKind) { +crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: clean::TypeKind) { let crate_name = cx.tcx.crate_name(did.krate).to_string(); let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { @@ -181,9 +181,9 @@ crate fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKin }; if did.is_local() { - cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn); + cx.renderinfo.exact_paths.insert(did, fqn); } else { - cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); + cx.renderinfo.external_paths.insert(did, (fqn, kind)); } } @@ -317,7 +317,7 @@ crate fn build_impl( attrs: Option<Attrs<'_>>, ret: &mut Vec<clean::Item>, ) { - if !cx.renderinfo.borrow_mut().inlined.insert(did) { + if !cx.renderinfo.inlined.insert(did) { return; } @@ -329,7 +329,7 @@ crate fn build_impl( if !did.is_local() { if let Some(traitref) = associated_trait { let did = traitref.def_id; - if !cx.renderinfo.borrow().access_levels.is_public(did) { + if !cx.renderinfo.access_levels.is_public(did) { return; } @@ -361,7 +361,7 @@ crate fn build_impl( // reachable in rustdoc generated documentation if !did.is_local() { if let Some(did) = for_.def_id() { - if !cx.renderinfo.borrow().access_levels.is_public(did) { + if !cx.renderinfo.access_levels.is_public(did) { return; } @@ -613,20 +613,19 @@ crate fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { } { - if cx.external_traits.borrow().contains_key(&did) - || cx.active_extern_traits.borrow().contains(&did) + if cx.external_traits.borrow().contains_key(&did) || cx.active_extern_traits.contains(&did) { return; } } { - cx.active_extern_traits.borrow_mut().insert(did); + cx.active_extern_traits.insert(did); } debug!("record_extern_trait: {:?}", did); let trait_ = build_external_trait(cx, did); cx.external_traits.borrow_mut().insert(did, trait_); - cx.active_extern_traits.borrow_mut().remove(&did); + cx.active_extern_traits.remove(&did); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 98e1299df2f..b6e70462105 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -357,7 +357,7 @@ impl Clean<Lifetime> for hir::Lifetime { | rl::Region::LateBound(_, node_id, _) | rl::Region::Free(_, node_id), ) => { - if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() { + if let Some(lt) = cx.lt_substs.get(&node_id).cloned() { return lt; } } @@ -644,7 +644,7 @@ impl Clean<Generics> for hir::Generics<'_> { match param.kind { GenericParamDefKind::Lifetime => unreachable!(), GenericParamDefKind::Type { did, ref bounds, .. } => { - cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone()); + cx.impl_trait_bounds.insert(did.into(), bounds.clone()); } GenericParamDefKind::Const { .. } => unreachable!(), } @@ -803,7 +803,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx unreachable!(); } - cx.impl_trait_bounds.borrow_mut().insert(param, bounds); + cx.impl_trait_bounds.insert(param, bounds); } // Now that `cx.impl_trait_bounds` is populated, we can process @@ -1291,10 +1291,10 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { match qpath { hir::QPath::Resolved(None, ref path) => { if let Res::Def(DefKind::TyParam, did) = path.res { - if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() { + if let Some(new_ty) = cx.ty_substs.get(&did).cloned() { return new_ty; } - if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) { + if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) { return ImplTrait(bounds); } } @@ -1304,7 +1304,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { // Substitute private type aliases if let Some(def_id) = def_id.as_local() { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) { + if !cx.renderinfo.access_levels.is_exported(def_id.to_def_id()) { alias = Some(&cx.tcx.hir().expect_item(hir_id).kind); } } @@ -1651,7 +1651,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { ty::Projection(ref data) => data.clean(cx), ty::Param(ref p) => { - if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) { + if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { ImplTrait(bounds) } else { Generic(p.name) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index c7bfd363a12..d2eee49f0c9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -23,10 +23,9 @@ crate fn krate(mut cx: &mut DocContext<'_>) -> Crate { let krate = cx.tcx.hir().krate(); let module = crate::visit_ast::RustdocVisitor::new(&mut cx).visit(krate); - let mut r = cx.renderinfo.get_mut(); - r.deref_trait_did = cx.tcx.lang_items().deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items().owned_box(); + cx.renderinfo.deref_trait_did = cx.tcx.lang_items().deref_trait(); + cx.renderinfo.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); + cx.renderinfo.owned_box_did = cx.tcx.lang_items().owned_box(); let mut externs = Vec::new(); for &cnum in cx.tcx.crates().iter() { @@ -494,10 +493,10 @@ crate fn enter_impl_trait<F, R>(cx: &mut DocContext<'_>, f: F) -> R where F: FnOnce(&mut DocContext<'_>) -> R, { - let old_bounds = mem::take(&mut *cx.impl_trait_bounds.get_mut()); + let old_bounds = mem::take(&mut cx.impl_trait_bounds); let r = f(cx); - assert!(cx.impl_trait_bounds.borrow().is_empty()); - *cx.impl_trait_bounds.get_mut() = old_bounds; + assert!(cx.impl_trait_bounds.is_empty()); + cx.impl_trait_bounds = old_bounds; r } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index dbf202a7321..8fceb00eeae 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -42,32 +42,37 @@ crate type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>; crate struct DocContext<'tcx> { crate tcx: TyCtxt<'tcx>, + /// Name resolver. Used for intra-doc links. + /// + /// The `Rc<RefCell<...>>` wrapping is needed because that is what's returned by + /// [`Queries::expansion()`]. + // FIXME: see if we can get rid of this RefCell somehow crate resolver: Rc<RefCell<interface::BoxedResolver>>, /// Used for normalization. /// /// Most of this logic is copied from rustc_lint::late. crate param_env: ParamEnv<'tcx>, /// Later on moved into `cache` - crate renderinfo: RefCell<RenderInfo>, + crate renderinfo: RenderInfo, /// Later on moved through `clean::Crate` into `cache` crate external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. - crate active_extern_traits: RefCell<FxHashSet<DefId>>, + crate active_extern_traits: FxHashSet<DefId>, // The current set of type and lifetime substitutions, // for expanding type aliases at the HIR level: /// Table `DefId` of type parameter -> substituted type - crate ty_substs: RefCell<FxHashMap<DefId, clean::Type>>, + crate ty_substs: FxHashMap<DefId, clean::Type>, /// Table `DefId` of lifetime parameter -> substituted lifetime - crate lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>, + crate lt_substs: FxHashMap<DefId, clean::Lifetime>, /// Table `DefId` of const parameter -> substituted const - crate ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>, + crate ct_substs: FxHashMap<DefId, clean::Constant>, /// Table synthetic type parameter for `impl Trait` in argument position -> bounds - crate impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>, + crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>, crate fake_def_ids: FxHashMap<CrateNum, DefIndex>, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set. - crate generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>, + crate generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>, crate auto_traits: Vec<DefId>, /// The options given to rustdoc that could be relevant to a pass. crate render_options: RenderOptions, @@ -112,14 +117,14 @@ impl<'tcx> DocContext<'tcx> { F: FnOnce(&mut Self) -> R, { let (old_tys, old_lts, old_cts) = ( - mem::replace(&mut *self.ty_substs.get_mut(), ty_substs), - mem::replace(&mut *self.lt_substs.get_mut(), lt_substs), - mem::replace(&mut *self.ct_substs.get_mut(), ct_substs), + mem::replace(&mut self.ty_substs, ty_substs), + mem::replace(&mut self.lt_substs, lt_substs), + mem::replace(&mut self.ct_substs, ct_substs), ); let r = f(self); - *self.ty_substs.get_mut() = old_tys; - *self.lt_substs.get_mut() = old_lts; - *self.ct_substs.get_mut() = old_cts; + self.ty_substs = old_tys; + self.lt_substs = old_lts; + self.ct_substs = old_cts; r } @@ -509,7 +514,7 @@ crate fn run_global_ctxt( param_env: ParamEnv::empty(), external_traits: Default::default(), active_extern_traits: Default::default(), - renderinfo: RefCell::new(renderinfo), + renderinfo, ty_substs: Default::default(), lt_substs: Default::default(), ct_substs: Default::default(), @@ -642,7 +647,7 @@ crate fn run_global_ctxt( // The main crate doc comments are always collapsed. krate.collapsed = true; - (krate, ctxt.renderinfo.into_inner(), ctxt.render_options) + (krate, ctxt.renderinfo, ctxt.render_options) } /// Due to <https://github.com/rust-lang/rust/pull/73566>, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 542cf6d2c27..c3365b844ec 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -127,7 +127,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { } fn print_results(&self) { - let output_format = self.ctx.renderinfo.borrow().output_format; + let output_format = self.ctx.renderinfo.output_format; if output_format.is_json() { println!("{}", self.to_json()); return; diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 0b6d81d1b44..0271a5b78a7 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -48,11 +48,10 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { if !cx.tcx.get_attrs(def_id).lists(sym::doc).has_word(sym::hidden) { let self_ty = cx.tcx.type_of(def_id); let impls = get_auto_trait_and_blanket_impls(cx, self_ty, def_id); - let mut renderinfo = cx.renderinfo.borrow_mut(); - new_items.extend(impls.filter(|i| renderinfo.inlined.insert(i.def_id))); + new_items.extend(impls.filter(|i| cx.renderinfo.inlined.insert(i.def_id))); } - }) + }); } } diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index 042a895d2fa..e8e1bead84f 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -97,8 +97,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { |lint| lint.build("missing code example in this documentation").emit(), ); } - } else if tests.found_tests > 0 && !cx.renderinfo.borrow().access_levels.is_public(item.def_id) - { + } else if tests.found_tests > 0 && !cx.renderinfo.access_levels.is_public(item.def_id) { cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index c0bb05af3ed..f83eab6799e 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -17,7 +17,7 @@ crate const STRIP_PRIVATE: Pass = Pass { crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { // This stripper collects all *retained* nodes. let mut retained = DefIdSet::default(); - let access_levels = cx.renderinfo.borrow().access_levels.clone(); + let access_levels = cx.renderinfo.access_levels.clone(); // strip all private items { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e92ea55caa7..4d42c181d8c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { assert_eq!(cur_mod_def_id, macro_parent_def_id); cur_mod.macros.push((def, None)); } - self.cx.renderinfo.get_mut().exact_paths = self.exact_paths; + self.cx.renderinfo.exact_paths = self.exact_paths; top_level_module } @@ -199,12 +199,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } else { // All items need to be handled here in case someone wishes to link // to them with intra-doc links - self.cx - .renderinfo - .get_mut() - .access_levels - .map - .insert(did, AccessLevel::Public); + self.cx.renderinfo.access_levels.map.insert(did, AccessLevel::Public); } } } @@ -216,7 +211,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { None => return false, }; - let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(res_did); + let is_private = !self.cx.renderinfo.access_levels.is_public(res_did); let is_hidden = inherits_doc_hidden(self.cx, res_hir_id); // Only inline if requested or if the item would otherwise be stripped. diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 0bf22562eae..daed5bd107d 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -25,7 +25,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { crate fn new(cx: &'a mut crate::core::DocContext<'tcx>) -> LibEmbargoVisitor<'a, 'tcx> { LibEmbargoVisitor { tcx: cx.tcx, - access_levels: &mut cx.renderinfo.get_mut().access_levels, + access_levels: &mut cx.renderinfo.access_levels, prev_level: Some(AccessLevel::Public), visited_mods: FxHashSet::default(), } diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index 7e705255d98..a3d4935f496 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -1,24 +1,28 @@ // edition:2018 -// @has nested.json "$.index[*][?(@.name=='nested')].kind" \"module\" -// @has - "$.index[*][?(@.name=='nested')].inner.is_crate" true +// @is nested.json "$.index[*][?(@.name=='nested')].kind" \"module\" +// @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true // @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1 -// @has nested.json "$.index[*][?(@.name=='l1')].kind" \"module\" -// @has - "$.index[*][?(@.name=='l1')].inner.is_crate" false +// @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\" +// @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false // @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2 pub mod l1 { - // @has nested.json "$.index[*][?(@.name=='l3')].kind" \"module\" - // @has - "$.index[*][?(@.name=='l3')].inner.is_crate" false + // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\" + // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false // @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1 + // @set l3_id = - "$.index[*][?(@.name=='l3')].id" + // @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id pub mod l3 { - // @has nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\" - // @has - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" + // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\" + // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" + // @set l4_id = - "$.index[*][?(@.name=='L4')].id" + // @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; } - // @has nested.json "$.index[*][?(@.inner.span=='l3::L4')].kind" \"import\" - // @has - "$.index[*][?(@.inner.span=='l3::L4')].inner.glob" false + // @is nested.json "$.index[*][?(@.inner.span=='l3::L4')].kind" \"import\" + // @is - "$.index[*][?(@.inner.span=='l3::L4')].inner.glob" false pub use l3::L4; } diff --git a/src/test/ui/borrowck/issue-81365-1.rs b/src/test/ui/borrowck/issue-81365-1.rs new file mode 100644 index 00000000000..8e212a77016 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-1.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-1.stderr b/src/test/ui/borrowck/issue-81365-1.stderr new file mode 100644 index 00000000000..ef88d7f14a3 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-1.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-1.rs:21:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-1.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-10.rs b/src/test/ui/borrowck/issue-81365-10.rs new file mode 100644 index 00000000000..7602e184a9f --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-10.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.deref().target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-10.stderr b/src/test/ui/borrowck/issue-81365-10.stderr new file mode 100644 index 00000000000..891f70ed7f6 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-10.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-10.rs:21:9 + | +LL | let first = &self.deref().target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-11.rs b/src/test/ui/borrowck/issue-81365-11.rs new file mode 100644 index 00000000000..6b558c65d3d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-11.rs @@ -0,0 +1,32 @@ +use std::ops::{Deref, DerefMut}; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl DerefMut for Container { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &mut self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-11.stderr b/src/test/ui/borrowck/issue-81365-11.stderr new file mode 100644 index 00000000000..0770c136632 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-11.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-11.rs:27:9 + | +LL | let first = &mut self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-2.rs b/src/test/ui/borrowck/issue-81365-2.rs new file mode 100644 index 00000000000..fbbdd93b97c --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-2.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.container.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-2.stderr b/src/test/ui/borrowck/issue-81365-2.stderr new file mode 100644 index 00000000000..e71edb50964 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-2.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-2.rs:25:9 + | +LL | let first = &self.container.target_field; + | -------------- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-2.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-3.rs b/src/test/ui/borrowck/issue-81365-3.rs new file mode 100644 index 00000000000..9a9e3a31358 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-3.rs @@ -0,0 +1,37 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-3.stderr b/src/test/ui/borrowck/issue-81365-3.stderr new file mode 100644 index 00000000000..70bb6bb93a9 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-3.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-3.rs:32:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-3.rs:23:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-4.rs b/src/test/ui/borrowck/issue-81365-4.rs new file mode 100644 index 00000000000..b2643eb3358 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-4.rs @@ -0,0 +1,38 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, + outer_field: bool, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.outer_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-4.stderr b/src/test/ui/borrowck/issue-81365-4.stderr new file mode 100644 index 00000000000..e714bb86d1c --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-4.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.outer_field` because it is borrowed + --> $DIR/issue-81365-4.rs:33:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.outer_field` occurs here +LL | self.outer_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.outer_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-4.rs:24:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-5.rs b/src/test/ui/borrowck/issue-81365-5.rs new file mode 100644 index 00000000000..d36b79615e3 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-5.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} + +impl DerefTarget { + fn get(&self) -> &bool { + &self.target_field + } +} + +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = self.get(); + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-5.stderr b/src/test/ui/borrowck/issue-81365-5.stderr new file mode 100644 index 00000000000..7c0e9f43bd0 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-5.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-5.rs:28:9 + | +LL | let first = self.get(); + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-5.rs:19:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-6.rs b/src/test/ui/borrowck/issue-81365-6.rs new file mode 100644 index 00000000000..85ea77756b3 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-6.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; + +struct Container { + target: Vec<()>, + container_field: bool, +} + +impl Deref for Container { + type Target = [()]; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self[0]; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-6.stderr b/src/test/ui/borrowck/issue-81365-6.stderr new file mode 100644 index 00000000000..85ed6acca3d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-6.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-6.rs:18:9 + | +LL | let first = &self[0]; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `[()]` +note: deref defined here + --> $DIR/issue-81365-6.rs:9:5 + | +LL | type Target = [()]; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-7.rs b/src/test/ui/borrowck/issue-81365-7.rs new file mode 100644 index 00000000000..cbf70f11a9a --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-7.rs @@ -0,0 +1,24 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +fn bad_borrow(c: &mut Container) { + let first = &c.target_field; + c.container_field = true; //~ ERROR E0506 + first; +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-7.stderr b/src/test/ui/borrowck/issue-81365-7.stderr new file mode 100644 index 00000000000..506732ec0c5 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-7.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `c.container_field` because it is borrowed + --> $DIR/issue-81365-7.rs:20:5 + | +LL | let first = &c.target_field; + | - borrow of `c.container_field` occurs here +LL | c.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `c.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-7.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-8.rs b/src/test/ui/borrowck/issue-81365-8.rs new file mode 100644 index 00000000000..0bb1033fb42 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-8.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &(*self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-8.stderr b/src/test/ui/borrowck/issue-81365-8.stderr new file mode 100644 index 00000000000..716b6e9b51f --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-8.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-8.rs:21:9 + | +LL | let first = &(*self).target_field; + | ------- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-8.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/issue-81365-9.rs b/src/test/ui/borrowck/issue-81365-9.rs new file mode 100644 index 00000000000..cd57afa288d --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-9.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &Deref::deref(self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-81365-9.stderr b/src/test/ui/borrowck/issue-81365-9.stderr new file mode 100644 index 00000000000..c7d48214fd4 --- /dev/null +++ b/src/test/ui/borrowck/issue-81365-9.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-9.rs:21:9 + | +LL | let first = &Deref::deref(self).target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/did_you_mean/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs deleted file mode 100644 index c5393703f70..00000000000 --- a/src/test/ui/did_you_mean/pub-macro-rules.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[macro_use] mod bleh { - pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation - ($n:ident) => ( - fn $n () -> i32 { - 1 - } - ) - } - -} - -foo!(meh); - -fn main() { - println!("{}", meh()); -} diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr deleted file mode 100644 index 0bde5783b8c..00000000000 --- a/src/test/ui/did_you_mean/pub-macro-rules.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: can't qualify macro_rules invocation with `pub` - --> $DIR/pub-macro-rules.rs:2:5 - | -LL | pub macro_rules! foo { - | ^^^ help: try exporting the macro: `#[macro_export]` - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs new file mode 100644 index 00000000000..5504ec317ae --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs @@ -0,0 +1,10 @@ +pub macro_rules! m1 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +#[cfg(FALSE)] +pub macro_rules! m2 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +pub(crate) macro_rules! m3 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +pub(in self) macro_rules! m4 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr new file mode 100644 index 00000000000..bfaec398d9a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr @@ -0,0 +1,39 @@ +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:1:1 + | +LL | pub macro_rules! m1 { () => {} } + | ^^^ + | + = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:4:1 + | +LL | pub macro_rules! m2 { () => {} } + | ^^^ + | + = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:6:1 + | +LL | pub(crate) macro_rules! m3 { () => {} } + | ^^^^^^^^^^ + | + = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:8:1 + | +LL | pub(in self) macro_rules! m4 { () => {} } + | ^^^^^^^^^^^^ + | + = note: see issue #78855 <https://github.com/rust-lang/rust/issues/78855> for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-81918.rs b/src/test/ui/issues/issue-81918.rs new file mode 100644 index 00000000000..8938b8a6f2c --- /dev/null +++ b/src/test/ui/issues/issue-81918.rs @@ -0,0 +1,11 @@ +// check-pass +// dont-check-compiler-stdout +// compile-flags: -Z unpretty=mir-cfg + +// This checks that unpretty=mir-cfg does not panic. See #81918. + +const TAG: &'static str = "ABCD"; + +fn main() { + if TAG == "" {} +} diff --git a/src/test/ui/lint/dead-code/write-only-field.rs b/src/test/ui/lint/dead-code/write-only-field.rs index 78cfcfda8f9..7b3f1e9f5b6 100644 --- a/src/test/ui/lint/dead-code/write-only-field.rs +++ b/src/test/ui/lint/dead-code/write-only-field.rs @@ -17,4 +17,53 @@ fn field_write(s: &mut S) { fn main() { let mut s = S { f: 0, sub: Sub { f: 0 } }; field_write(&mut s); + + auto_deref(); + nested_boxes(); +} + +fn auto_deref() { + struct E { + x: bool, + y: bool, //~ ERROR: field is never read + } + + struct P<'a> { + e: &'a mut E + } + + impl P<'_> { + fn f(&mut self) { + self.e.x = true; + self.e.y = true; + } + } + + let mut e = E { x: false, y: false }; + let mut p = P { e: &mut e }; + p.f(); + assert!(e.x); +} + +fn nested_boxes() { + struct A { + b: Box<B>, + } + + struct B { + c: Box<C>, + } + + struct C { + u: u32, //~ ERROR: field is never read + v: u32, //~ ERROR: field is never read + } + + let mut a = A { + b: Box::new(B { + c: Box::new(C { u: 0, v: 0 }), + }), + }; + a.b.c.v = 10; + a.b.c = Box::new(C { u: 1, v: 2 }); } diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index 70d2149665b..a191d22c8b9 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -22,5 +22,23 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ -error: aborting due to 3 previous errors +error: field is never read: `y` + --> $DIR/write-only-field.rs:28:9 + | +LL | y: bool, + | ^^^^^^^ + +error: field is never read: `u` + --> $DIR/write-only-field.rs:58:9 + | +LL | u: u32, + | ^^^^^^ + +error: field is never read: `v` + --> $DIR/write-only-field.rs:59:9 + | +LL | v: u32, + | ^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.rs b/src/test/ui/macros/macro-export-on-modularized-macros.rs new file mode 100644 index 00000000000..467c6ba7b78 --- /dev/null +++ b/src/test/ui/macros/macro-export-on-modularized-macros.rs @@ -0,0 +1,11 @@ +#![feature(decl_macro)] +#![feature(pub_macro_rules)] + +#[macro_export] +macro m1() {} //~ ERROR `#[macro_export]` cannot be used on `macro` items + +#[macro_export] +pub macro_rules! m2 { () => {} } +//~^ ERROR `#[macro_export]` cannot be used on `macro_rules` with `pub` + +fn main() {} diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.stderr b/src/test/ui/macros/macro-export-on-modularized-macros.stderr new file mode 100644 index 00000000000..8bb031e12cb --- /dev/null +++ b/src/test/ui/macros/macro-export-on-modularized-macros.stderr @@ -0,0 +1,14 @@ +error: `#[macro_export]` cannot be used on `macro` items + --> $DIR/macro-export-on-modularized-macros.rs:5:1 + | +LL | macro m1() {} + | ^^^^^^^^^^^^^ + +error: `#[macro_export]` cannot be used on `macro_rules` with `pub` + --> $DIR/macro-export-on-modularized-macros.rs:8:1 + | +LL | pub macro_rules! m2 { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macros/pub-macro-rules-fail.rs b/src/test/ui/macros/pub-macro-rules-fail.rs new file mode 100644 index 00000000000..bdb4c73f18b --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules-fail.rs @@ -0,0 +1,28 @@ +#![feature(pub_macro_rules)] + +#[macro_use] +mod m { + pub macro_rules! mac { () => {} } + + // `pub` `macro_rules` cannot be redefined in the same module. + pub macro_rules! mac { () => {} } //~ ERROR the name `mac` is defined multiple times + + pub(self) macro_rules! private_mac { () => {} } +} + +const _: () = { + pub macro_rules! block_mac { () => {} } +}; + +mod n { + // Scope of `pub` `macro_rules` is not extended by `#[macro_use]`. + mac!(); //~ ERROR cannot find macro `mac` in this scope + + // `pub` `macro_rules` doesn't put the macro into the root module, unlike `#[macro_export]`. + crate::mac!(); //~ ERROR failed to resolve: maybe a missing crate `mac` + crate::block_mac!(); //~ ERROR failed to resolve: maybe a missing crate `block_mac` + + crate::m::private_mac!(); //~ ERROR macro `private_mac` is private +} + +fn main() {} diff --git a/src/test/ui/macros/pub-macro-rules-fail.stderr b/src/test/ui/macros/pub-macro-rules-fail.stderr new file mode 100644 index 00000000000..588d79dd76a --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules-fail.stderr @@ -0,0 +1,48 @@ +error[E0428]: the name `mac` is defined multiple times + --> $DIR/pub-macro-rules-fail.rs:8:5 + | +LL | pub macro_rules! mac { () => {} } + | -------------------- previous definition of the macro `mac` here +... +LL | pub macro_rules! mac { () => {} } + | ^^^^^^^^^^^^^^^^^^^^ `mac` redefined here + | + = note: `mac` must be defined only once in the macro namespace of this module + +error[E0433]: failed to resolve: maybe a missing crate `mac`? + --> $DIR/pub-macro-rules-fail.rs:22:12 + | +LL | crate::mac!(); + | ^^^ maybe a missing crate `mac`? + +error[E0433]: failed to resolve: maybe a missing crate `block_mac`? + --> $DIR/pub-macro-rules-fail.rs:23:12 + | +LL | crate::block_mac!(); + | ^^^^^^^^^ maybe a missing crate `block_mac`? + +error: cannot find macro `mac` in this scope + --> $DIR/pub-macro-rules-fail.rs:19:5 + | +LL | mac!(); + | ^^^ + | + = note: consider importing this macro: + m::mac + +error[E0603]: macro `private_mac` is private + --> $DIR/pub-macro-rules-fail.rs:25:15 + | +LL | crate::m::private_mac!(); + | ^^^^^^^^^^^ private macro + | +note: the macro `private_mac` is defined here + --> $DIR/pub-macro-rules-fail.rs:10:5 + | +LL | pub(self) macro_rules! private_mac { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0428, E0433, E0603. +For more information about an error, try `rustc --explain E0428`. diff --git a/src/test/ui/macros/pub-macro-rules.rs b/src/test/ui/macros/pub-macro-rules.rs new file mode 100644 index 00000000000..cd4a845f7c0 --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(pub_macro_rules)] + +mod m { + // `pub` `macro_rules` can be used earlier in item order than they are defined. + foo!(); + + pub macro_rules! foo { () => {} } + + // `pub(...)` works too. + pub(super) macro_rules! bar { () => {} } +} + +// `pub` `macro_rules` are available by module path. +m::foo!(); + +m::bar!(); + +fn main() {} diff --git a/src/test/ui/non-fmt-panic.rs b/src/test/ui/non-fmt-panic.rs index 25c53316e12..c80a90b3eaa 100644 --- a/src/test/ui/non-fmt-panic.rs +++ b/src/test/ui/non-fmt-panic.rs @@ -29,6 +29,17 @@ fn main() { fancy_panic::fancy_panic!(S); //~^ WARN panic message is not a string literal + macro_rules! a { + () => { 123 }; + } + + panic!(a!()); //~ WARN panic message is not a string literal + + panic!(format!("{}", 1)); //~ WARN panic message is not a string literal + + panic![123]; //~ WARN panic message is not a string literal + panic!{123}; //~ WARN panic message is not a string literal + // Check that the lint only triggers for std::panic and core::panic, // not any panic macro: macro_rules! panic { diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index 45187c518c4..7a333b3e76a 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -93,7 +93,7 @@ LL | panic!("{}", C); help: or use std::panic::panic_any instead | LL | std::panic::panic_any(C); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:20:12 @@ -109,7 +109,7 @@ LL | panic!("{}", S); help: or use std::panic::panic_any instead | LL | std::panic::panic_any(S); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:21:17 @@ -125,7 +125,7 @@ LL | std::panic!("{}", 123); help: or use std::panic::panic_any instead | LL | std::panic::panic_any(123); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ warning: panic message is not a string literal --> $DIR/non-fmt-panic.rs:22:18 @@ -183,5 +183,66 @@ LL | fancy_panic::fancy_panic!(S); | = note: this is no longer accepted in Rust 2021 -warning: 14 warnings emitted +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:36:12 + | +LL | panic!(a!()); + | ^^^^ + | + = note: this is no longer accepted in Rust 2021 +help: add a "{}" format string to Display the message + | +LL | panic!("{}", a!()); + | ^^^^^ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(a!()); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:38:12 + | +LL | panic!(format!("{}", 1)); + | ^^^^^^^^^^^^^^^^ + | + = note: this is no longer accepted in Rust 2021 + = note: the panic!() macro supports formatting, so there's no need for the format!() macro here +help: remove the `format!(..)` macro call + | +LL | panic!("{}", 1); + | -- -- + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:40:12 + | +LL | panic![123]; + | ^^^ + | + = note: this is no longer accepted in Rust 2021 +help: add a "{}" format string to Display the message + | +LL | panic!["{}", 123]; + | ^^^^^ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(123); + | ^^^^^^^^^^^^^^^^^^^^^^ ^ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:41:12 + | +LL | panic!{123}; + | ^^^ + | + = note: this is no longer accepted in Rust 2021 +help: add a "{}" format string to Display the message + | +LL | panic!{"{}", 123}; + | ^^^^^ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(123); + | ^^^^^^^^^^^^^^^^^^^^^^ ^ + +warning: 18 warnings emitted diff --git a/src/test/ui/pattern/issue-82290.rs b/src/test/ui/pattern/issue-82290.rs new file mode 100644 index 00000000000..67f0274fe74 --- /dev/null +++ b/src/test/ui/pattern/issue-82290.rs @@ -0,0 +1,7 @@ +#![feature(let_chains)] //~ WARN the feature `let_chains` is incomplete + +fn main() { + if true && let x = 1 { //~ ERROR `let` expressions are not supported here + let _ = x; + } +} diff --git a/src/test/ui/pattern/issue-82290.stderr b/src/test/ui/pattern/issue-82290.stderr new file mode 100644 index 00000000000..65ef018dc97 --- /dev/null +++ b/src/test/ui/pattern/issue-82290.stderr @@ -0,0 +1,20 @@ +error: `let` expressions are not supported here + --> $DIR/issue-82290.rs:4:16 + | +LL | if true && let x = 1 { + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if`- and `while`-expressions + = note: as well as when nested within `&&` and parenthesis in those conditions + +warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-82290.rs:1:12 + | +LL | #![feature(let_chains)] + | ^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs index b742f0eb3ee..8a6a911321c 100644 --- a/src/tools/jsondocck/src/cache.rs +++ b/src/tools/jsondocck/src/cache.rs @@ -9,6 +9,7 @@ pub struct Cache { root: PathBuf, files: HashMap<PathBuf, String>, values: HashMap<PathBuf, Value>, + pub variables: HashMap<String, Value>, last_path: Option<PathBuf>, } @@ -19,6 +20,7 @@ impl Cache { root: Path::new(doc_dir).to_owned(), files: HashMap::new(), values: HashMap::new(), + variables: HashMap::new(), last_path: None, } } diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index 6ec292aba64..5020a4917a0 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -2,6 +2,7 @@ use jsonpath_lib::select; use lazy_static::lazy_static; use regex::{Regex, RegexBuilder}; use serde_json::Value; +use std::borrow::Cow; use std::{env, fmt, fs}; mod cache; @@ -48,13 +49,16 @@ pub struct Command { pub enum CommandKind { Has, Count, + Is, + Set, } impl CommandKind { fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool { let count = match self { CommandKind::Has => (1..=3).contains(&args.len()), - CommandKind::Count => 3 == args.len(), + CommandKind::Count | CommandKind::Is => 3 == args.len(), + CommandKind::Set => 4 == args.len(), }; if !count { @@ -83,6 +87,8 @@ impl fmt::Display for CommandKind { let text = match self { CommandKind::Has => "has", CommandKind::Count => "count", + CommandKind::Is => "is", + CommandKind::Set => "set", }; write!(f, "{}", text) } @@ -127,6 +133,8 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> { let cmd = match cmd { "has" => CommandKind::Has, "count" => CommandKind::Count, + "is" => CommandKind::Is, + "set" => CommandKind::Set, _ => { print_err(&format!("Unrecognized command name `@{}`", cmd), lineno); errors = true; @@ -180,6 +188,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> { /// Performs the actual work of ensuring a command passes. Generally assumes the command /// is syntactically valid. fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { + // FIXME: Be more granular about why, (e.g. syntax error, count not equal) let result = match command.kind { CommandKind::Has => { match command.args.len() { @@ -188,23 +197,15 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { // @has <path> <jsonpath> = check path exists 2 => { let val = cache.get_value(&command.args[0])?; - - match select(&val, &command.args[1]) { - Ok(results) => !results.is_empty(), - Err(_) => false, - } + let results = select(&val, &command.args[1]).unwrap(); + !results.is_empty() } // @has <path> <jsonpath> <value> = check *any* item matched by path equals value 3 => { let val = cache.get_value(&command.args[0])?; - match select(&val, &command.args[1]) { - Ok(results) => { - let pat: Value = serde_json::from_str(&command.args[2]).unwrap(); - - !results.is_empty() && results.into_iter().any(|val| *val == pat) - } - Err(_) => false, - } + let results = select(&val, &command.args[1]).unwrap(); + let pat = string_to_value(&command.args[2], cache); + results.contains(&pat.as_ref()) } _ => unreachable!(), } @@ -215,9 +216,37 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { let expected: usize = command.args[2].parse().unwrap(); let val = cache.get_value(&command.args[0])?; - match select(&val, &command.args[1]) { - Ok(results) => results.len() == expected, - Err(_) => false, + let results = select(&val, &command.args[1]).unwrap(); + results.len() == expected + } + CommandKind::Is => { + // @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value + assert_eq!(command.args.len(), 3); + let val = cache.get_value(&command.args[0])?; + let results = select(&val, &command.args[1]).unwrap(); + let pat = string_to_value(&command.args[2], cache); + results.len() == 1 && results[0] == pat.as_ref() + } + CommandKind::Set => { + // @set <name> = <path> <jsonpath> + assert_eq!(command.args.len(), 4); + assert_eq!(command.args[1], "=", "Expected an `=`"); + let val = cache.get_value(&command.args[2])?; + let results = select(&val, &command.args[3]).unwrap(); + assert_eq!(results.len(), 1); + match results.len() { + 0 => false, + 1 => { + let r = cache.variables.insert(command.args[0].clone(), results[0].clone()); + assert!(r.is_none(), "Name collision: {} is duplicated", command.args[0]); + true + } + _ => { + panic!( + "Got multiple results in `@set` for `{}`: {:?}", + &command.args[3], results + ); + } } } }; @@ -247,3 +276,11 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { Ok(()) } } + +fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> { + if s.starts_with("$") { + Cow::Borrowed(&cache.variables[&s[1..]]) + } else { + Cow::Owned(serde_json::from_str(s).unwrap()) + } +} |
