diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 44bb44cb7288..a09aa9ee6651 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -23,7 +23,7 @@ use crate::ast::*; use crate::ptr::P; use crate::token::{self, Token}; use crate::tokenstream::*; -use crate::visit::{AssocCtxt, BoundKind}; +use crate::visit::{AssocCtxt, BoundKind, FnCtxt}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -37,7 +37,16 @@ impl ExpectOne for SmallVec { } pub trait WalkItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor); + type Ctxt; + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ); } pub trait MutVisitor: Sized { @@ -114,9 +123,9 @@ pub trait MutVisitor: Sized { fn flat_map_assoc_item( &mut self, i: P, - _ctxt: AssocCtxt, + ctxt: AssocCtxt, ) -> SmallVec<[P; 1]> { - walk_flat_map_item(self, i) + walk_flat_map_assoc_item(self, i, ctxt) } fn visit_fn_decl(&mut self, d: &mut P) { @@ -880,7 +889,7 @@ fn walk_coroutine_kind(vis: &mut T, coroutine_kind: &mut Coroutin fn walk_fn(vis: &mut T, kind: FnKind<'_>) { match kind { - FnKind::Fn(FnSig { header, decl, span }, generics, body) => { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span }, _visibility, generics, body) => { // Identifier and visibility are visited as a part of the item. vis.visit_fn_header(header); vis.visit_generics(generics); @@ -890,8 +899,9 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { } vis.visit_span(span); } - FnKind::Closure(binder, decl, body) => { + FnKind::Closure(binder, coroutine_kind, decl, body) => { vis.visit_closure_binder(binder); + coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); vis.visit_fn_decl(decl); vis.visit_expr(body); } @@ -1079,17 +1089,29 @@ pub fn walk_block(vis: &mut T, block: &mut P) { vis.visit_span(span); } -pub fn walk_item_kind( - kind: &mut impl WalkItemKind, +pub fn walk_item_kind( + kind: &mut K, span: Span, id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: K::Ctxt, vis: &mut impl MutVisitor, ) { - kind.walk(span, id, vis) + kind.walk(span, id, ident, visibility, ctxt, vis) } impl WalkItemKind for ItemKind { - fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) { + type Ctxt = (); + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + _ctxt: Self::Ctxt, + vis: &mut impl MutVisitor, + ) { match self { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), @@ -1102,7 +1124,11 @@ impl WalkItemKind for ItemKind { } ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(vis, defaultness); - vis.visit_fn(FnKind::Fn(sig, generics, body), span, id); + vis.visit_fn( + FnKind::Fn(FnCtxt::Free, ident, sig, visibility, generics, body), + span, + id, + ); } ItemKind::Mod(safety, mod_kind) => { visit_safety(vis, safety); @@ -1201,14 +1227,27 @@ impl WalkItemKind for ItemKind { } impl WalkItemKind for AssocItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) { + type Ctxt = AssocCtxt; + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ) { match self { AssocItemKind::Const(item) => { visit_const_item(item, visitor); } AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(visitor, defaultness); - visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id); + visitor.visit_fn( + FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, visibility, generics, body), + span, + id, + ); } AssocItemKind::Type(box TyAlias { defaultness, @@ -1288,24 +1327,40 @@ pub fn walk_crate(vis: &mut T, krate: &mut Crate) { vis.visit_span(inject_use_span); } -/// Mutates one item, returning the item again. -pub fn walk_flat_map_item( +pub fn walk_flat_map_item>( + visitor: &mut impl MutVisitor, + item: P>, +) -> SmallVec<[P>; 1]> { + walk_flat_map_assoc_item(visitor, item, ()) +} + +pub fn walk_flat_map_assoc_item( visitor: &mut impl MutVisitor, mut item: P>, + ctxt: K::Ctxt, ) -> SmallVec<[P>; 1]> { let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut(); visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); visitor.visit_ident(ident); - kind.walk(*span, *id, visitor); + kind.walk(*span, *id, ident, vis, ctxt, visitor); visit_lazy_tts(visitor, tokens); visitor.visit_span(span); smallvec![item] } impl WalkItemKind for ForeignItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) { + type Ctxt = (); + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + _ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ) { match self { ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { visitor.visit_ty(ty); @@ -1313,7 +1368,11 @@ impl WalkItemKind for ForeignItemKind { } ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(visitor, defaultness); - visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id); + visitor.visit_fn( + FnKind::Fn(FnCtxt::Foreign, ident, sig, visibility, generics, body), + span, + id, + ); } ForeignItemKind::TyAlias(box TyAlias { defaultness, @@ -1522,9 +1581,8 @@ pub fn walk_expr(vis: &mut T, Expr { kind, id, span, attrs, token fn_arg_span, }) => { visit_constness(vis, constness); - coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); vis.visit_capture_by(capture_clause); - vis.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id); + vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id); vis.visit_span(fn_decl_span); vis.visit_span(fn_arg_span); } @@ -1785,8 +1843,20 @@ impl DummyAstNode for crate::ast_traits::AstNo #[derive(Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(&'a mut FnSig, &'a mut Generics, &'a mut Option>), + Fn( + FnCtxt, + &'a mut Ident, + &'a mut FnSig, + &'a mut Visibility, + &'a mut Generics, + &'a mut Option>, + ), /// E.g., `|x, y| body`. - Closure(&'a mut ClosureBinder, &'a mut P, &'a mut P), + Closure( + &'a mut ClosureBinder, + &'a mut Option, + &'a mut P, + &'a mut P, + ), } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ef6f126f54c8..3500c2153765 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -66,7 +66,7 @@ impl BoundKind { #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>), + Fn(FnCtxt, &'a Ident, &'a FnSig, &'a Visibility, &'a Generics, &'a Option>), /// E.g., `|x, y| body`. Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), @@ -112,11 +112,15 @@ pub enum LifetimeCtxt { GenericArg, } -pub trait WalkItemKind: Sized { +pub trait WalkItemKind { + type Ctxt; fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + visibility: &'a Visibility, + ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result; } @@ -340,16 +344,19 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR } impl WalkItemKind for ItemKind { + type Ctxt = (); fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - _ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let Item { id, span, vis, ident, .. } = item; match self { ItemKind::ExternCrate(_rename) => {} - ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, *id, false)), + ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); @@ -360,8 +367,8 @@ impl WalkItemKind for ItemKind { visit_opt!(visitor, visit_expr, expr); } ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref()); - try_visit!(visitor.visit_fn(kind, *span, *id)); + let kind = FnKind::Fn(FnCtxt::Free, ident, sig, vis, generics, body); + try_visit!(visitor.visit_fn(kind, span, id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { ModKind::Loaded(items, _inline, _inner_span) => { @@ -418,7 +425,7 @@ impl WalkItemKind for ItemKind { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, *id)), + ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)), ItemKind::Delegation(box Delegation { id, qself, @@ -434,7 +441,7 @@ impl WalkItemKind for ItemKind { } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(walk_qself(visitor, qself)); - try_visit!(visitor.visit_path(prefix, *id)); + try_visit!(visitor.visit_path(prefix, id)); if let Some(suffixes) = suffixes { for (ident, rename) in suffixes { visitor.visit_ident(ident); @@ -452,9 +459,9 @@ impl WalkItemKind for ItemKind { pub fn walk_item<'a, V: Visitor<'a>>( visitor: &mut V, - item: &'a Item, + item: &'a Item>, ) -> V::Result { - walk_assoc_item(visitor, item, AssocCtxt::Trait /*ignored*/) + walk_assoc_item(visitor, item, ()) } pub fn walk_enum_def<'a, V: Visitor<'a>>( @@ -684,20 +691,23 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res } impl WalkItemKind for ForeignItemKind { + type Ctxt = (); fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - _ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let &Item { id, span, ident, ref vis, .. } = item; match self { ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body); try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { @@ -850,13 +860,16 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu } impl WalkItemKind for AssocItemKind { + type Ctxt = AssocCtxt; fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let &Item { id, span, ident, ref vis, .. } = item; match self { AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { try_visit!(visitor.visit_generics(generics)); @@ -864,8 +877,7 @@ impl WalkItemKind for AssocItemKind { visit_opt!(visitor, visit_expr, expr); } AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = - FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body); try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { @@ -913,16 +925,16 @@ impl WalkItemKind for AssocItemKind { } } -pub fn walk_assoc_item<'a, V: Visitor<'a>>( +pub fn walk_assoc_item<'a, V: Visitor<'a>, K: WalkItemKind>( visitor: &mut V, - item: &'a Item, - ctxt: AssocCtxt, + item: &'a Item, + ctxt: K::Ctxt, ) -> V::Result { - let Item { id: _, span: _, ident, vis, attrs, kind, tokens: _ } = item; + let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); try_visit!(visitor.visit_ident(ident)); - try_visit!(kind.walk(item, ctxt, visitor)); + try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor)); V::Result::output() } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dee48586f34c..07a6f4e5ee73 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -946,8 +946,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = - FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Free, &item.ident, sig, &item.vis, generics, body); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -1476,14 +1475,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = FnKind::Fn( - FnCtxt::Assoc(ctxt), - item.ident, - sig, - &item.vis, - generics, - body.as_deref(), - ); + let kind = + FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, sig, &item.vis, generics, body); walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index d832decc1708..7adc7a8863e4 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,93 +1,171 @@ +use std::fmt; + use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges}; +use rustc_middle::mir::{ + self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, +}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; -use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable}; +use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects}; use tracing::debug; use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict}; -/// The results of the dataflow analyses used by the borrow checker. -pub(crate) struct BorrowckResults<'a, 'tcx> { - pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>, - pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, - pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>, -} - -/// The transient state of the dataflow analyses used by the borrow checker. -#[derive(Debug)] -pub(crate) struct BorrowckDomain<'a, 'tcx> { - pub(crate) borrows: as Analysis<'tcx>>::Domain, - pub(crate) uninits: as Analysis<'tcx>>::Domain, - pub(crate) ever_inits: as Analysis<'tcx>>::Domain, +// This analysis is different to most others. Its results aren't computed with +// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are +// computed individually with `iterate_to_fixpoint`. +pub(crate) struct Borrowck<'a, 'tcx> { + pub(crate) borrows: Borrows<'a, 'tcx>, + pub(crate) uninits: MaybeUninitializedPlaces<'a, 'tcx>, + pub(crate) ever_inits: EverInitializedPlaces<'a, 'tcx>, } -impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> { - type Direction = Forward; +impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { type Domain = BorrowckDomain<'a, 'tcx>; + const NAME: &'static str = "borrowck"; + fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { BorrowckDomain { - borrows: self.borrows.analysis.bottom_value(body), - uninits: self.uninits.analysis.bottom_value(body), - ever_inits: self.ever_inits.analysis.bottom_value(body), + borrows: self.borrows.bottom_value(body), + uninits: self.uninits.bottom_value(body), + ever_inits: self.ever_inits.bottom_value(body), } } - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) { - state.borrows.clone_from(self.borrows.entry_set_for_block(block)); - state.uninits.clone_from(self.uninits.entry_set_for_block(block)); - state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block)); + fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _state: &mut Self::Domain) { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); } - fn reconstruct_before_statement_effect( + fn apply_before_statement_effect( &mut self, state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, loc: Location, ) { - self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc); + self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc); } - fn reconstruct_statement_effect( + fn apply_statement_effect( &mut self, state: &mut Self::Domain, stmt: &mir::Statement<'tcx>, loc: Location, ) { - self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc); + self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc); } - fn reconstruct_before_terminator_effect( + fn apply_before_terminator_effect( &mut self, state: &mut Self::Domain, term: &mir::Terminator<'tcx>, loc: Location, ) { - self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc); - self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc); + self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc); } - fn reconstruct_terminator_effect( + fn apply_terminator_effect<'mir>( &mut self, state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, + term: &'mir mir::Terminator<'tcx>, loc: Location, + ) -> TerminatorEdges<'mir, 'tcx> { + self.borrows.apply_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc); + + // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this + // analysis doesn't use. + TerminatorEdges::None + } + + fn apply_call_return_effect( + &mut self, + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } + + fn apply_switch_int_edge_effects( + &mut self, + _block: BasicBlock, + _discr: &mir::Operand<'tcx>, + _apply_edge_effects: &mut impl SwitchIntEdgeEffects, ) { - self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc); - self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc); + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); } } +impl JoinSemiLattice for BorrowckDomain<'_, '_> { + fn join(&mut self, _other: &Self) -> bool { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } +} + +impl<'tcx, C> DebugWithContext for BorrowckDomain<'_, 'tcx> +where + C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>, +{ + fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("borrows: ")?; + self.borrows.fmt_with(ctxt, f)?; + f.write_str(" uninits: ")?; + self.uninits.fmt_with(ctxt, f)?; + f.write_str(" ever_inits: ")?; + self.ever_inits.fmt_with(ctxt, f)?; + Ok(()) + } + + fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self == old { + return Ok(()); + } + + if self.borrows != old.borrows { + f.write_str("borrows: ")?; + self.borrows.fmt_diff_with(&old.borrows, ctxt, f)?; + f.write_str("\n")?; + } + + if self.uninits != old.uninits { + f.write_str("uninits: ")?; + self.uninits.fmt_diff_with(&old.uninits, ctxt, f)?; + f.write_str("\n")?; + } + + if self.ever_inits != old.ever_inits { + f.write_str("ever_inits: ")?; + self.ever_inits.fmt_diff_with(&old.ever_inits, ctxt, f)?; + f.write_str("\n")?; + } + + Ok(()) + } +} + +/// The transient state of the dataflow analyses used by the borrow checker. +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct BorrowckDomain<'a, 'tcx> { + pub(crate) borrows: as Analysis<'tcx>>::Domain, + pub(crate) uninits: as Analysis<'tcx>>::Domain, + pub(crate) ever_inits: as Analysis<'tcx>>::Domain, +} + rustc_index::newtype_index! { #[orderable] #[debug_format = "bw{}"] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 657e6e0907ca..7eaf265d4101 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -36,13 +36,13 @@ use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, }; +use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use smallvec::SmallVec; @@ -50,7 +50,7 @@ use tracing::{debug, instrument}; use crate::borrow_set::{BorrowData, BorrowSet}; use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions}; -use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows}; +use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows}; use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName}; use crate::location::LocationTable; use crate::nll::PoloniusOutput; @@ -221,6 +221,10 @@ fn do_mir_borrowck<'tcx>( consumer_options, ); + // `flow_inits` is large, so we drop it as soon as possible. This reduces + // peak memory usage significantly on some benchmarks. + drop(flow_inits); + // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set); @@ -229,27 +233,6 @@ fn do_mir_borrowck<'tcx>( // information. nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags); - // The various `flow_*` structures can be large. We drop `flow_inits` here - // so it doesn't overlap with the others below. This reduces peak memory - // usage significantly on some benchmarks. - drop(flow_inits); - - let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let movable_coroutine = // The first argument is the coroutine type passed by value if let Some(local) = body.local_decls.raw.get(1) @@ -334,16 +317,11 @@ fn do_mir_borrowck<'tcx>( // Compute and report region errors, if any. mbcx.report_region_errors(nll_errors); - let mut results = BorrowckResults { - ever_inits: flow_ever_inits, - uninits: flow_uninits, - borrows: flow_borrows, - }; - - rustc_mir_dataflow::visit_results( + let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx); + visit_results( body, traversal::reverse_postorder(body).map(|(bb, _)| bb), - &mut results, + &mut flow_results, &mut mbcx, ); @@ -426,6 +404,47 @@ fn do_mir_borrowck<'tcx>( (result, body_with_facts) } +fn get_flow_results<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + body: &'a Body<'tcx>, + move_data: &'a MoveData<'tcx>, + borrow_set: &'a BorrowSet<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, +) -> Results<'tcx, Borrowck<'a, 'tcx>> { + // We compute these three analyses individually, but them combine them into + // a single results so that `mbcx` can visit them all together. + let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let uninits = MaybeUninitializedPlaces::new(tcx, body, move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let ever_inits = EverInitializedPlaces::new(body, move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + + let analysis = Borrowck { + borrows: borrows.analysis, + uninits: uninits.analysis, + ever_inits: ever_inits.analysis, + }; + + assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len()); + assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len()); + let entry_sets: EntrySets<'_, Borrowck<'_, '_>> = + itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets) + .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits }) + .collect(); + + Results { analysis, entry_sets } +} + pub(crate) struct BorrowckInferCtxt<'tcx> { pub(crate) infcx: InferCtxt<'tcx>, pub(crate) reg_var_to_origin: RefCell>, @@ -588,14 +607,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> - for MirBorrowckCtxt<'a, '_, 'tcx> -{ - type Domain = BorrowckDomain<'a, 'tcx>; - +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> { fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, stmt: &'a Statement<'tcx>, location: Location, @@ -667,7 +682,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, @@ -780,7 +795,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index f419c1e776b8..e7ee6b43e27a 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -204,10 +204,10 @@ impl MutVisitor for CfgEval<'_> { fn flat_map_assoc_item( &mut self, item: P, - _ctxt: AssocCtxt, + ctxt: AssocCtxt, ) -> SmallVec<[P; 1]> { let item = configure!(self, item); - mut_visit::walk_flat_map_item(self, item) + mut_visit::walk_flat_map_assoc_item(self, item, ctxt) } fn flat_map_foreign_item( diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 953484533087..ba5d34359aa2 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -144,7 +144,15 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { item.kind { let prev_tests = mem::take(&mut self.tests); - walk_item_kind(&mut item.kind, item.span, item.id, self); + walk_item_kind( + &mut item.kind, + item.span, + item.id, + &mut item.ident, + &mut item.vis, + (), + self, + ); self.add_test_cases(item.id, span, prev_tests); } else { // But in those cases, we emit a lint to warn the user of these missing tests. diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 04ac7891023f..91786462b404 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1303,7 +1303,7 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> fragment.make_trait_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self.wrapped) + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Trait) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1344,7 +1344,7 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> fragment.make_impl_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self.wrapped) + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 610c69e9d21b..90206b19bd58 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -286,7 +286,7 @@ impl MutVisitor for PlaceholderExpander { AssocCtxt::Impl => it.make_impl_items(), } } - _ => walk_flat_map_item(self, item), + _ => walk_flat_map_assoc_item(self, item, ctxt), } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index cc55f57c46cc..b4b3ef31f97a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -177,6 +177,7 @@ enum Scope<'a> { LateBoundary { s: ScopeRef<'a>, what: &'static str, + deny_late_regions: bool, }, Root { @@ -234,9 +235,11 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("s", &"..") .finish(), Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), - Scope::LateBoundary { s: _, what } => { - f.debug_struct("LateBoundary").field("what", what).finish() - } + Scope::LateBoundary { s: _, what, deny_late_regions } => f + .debug_struct("LateBoundary") + .field("what", what) + .field("deny_late_regions", deny_late_regions) + .finish(), Scope::Root { opt_parent_item } => { f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish() } @@ -573,17 +576,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // give, we will reverse the IndexMap after early captures. let mut late_depth = 0; let mut scope = self.scope; - let mut crossed_late_boundary = None; let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)]; loop { match *scope { Scope::Binder { ref bound_vars, scope_type, s, .. } => { for (&original_lifetime, &def) in bound_vars.iter().rev() { - if let ResolvedArg::LateBound(..) = def - && crossed_late_boundary.is_some() - { - continue; - } if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) { let def = def.shifted(late_depth); let ident = lifetime_ident(original_lifetime); @@ -624,12 +621,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { - scope = s; - } - - Scope::LateBoundary { s, what, .. } => { - crossed_late_boundary = Some(what); + | Scope::TraitRefBoundary { s, .. } + | Scope::LateBoundary { s, .. } => { scope = s; } } @@ -640,7 +633,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope }; self.with(scope, |this| { let scope = Scope::TraitRefBoundary { s: this.scope }; - this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque)) + this.with(scope, |this| { + let scope = Scope::LateBoundary { + s: this.scope, + what: "nested `impl Trait`", + // We can capture late-bound regions; we just don't duplicate + // lifetime or const params, so we can't allow those. + deny_late_regions: false, + }; + this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque)) + }) }); let captures = captures.into_inner().into_iter().collect(); @@ -997,9 +999,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { - self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| { - intravisit::walk_anon_const(this, c); - }); + self.with( + Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true }, + |this| { + intravisit::walk_anon_const(this, c); + }, + ); } fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) { @@ -1291,8 +1296,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { scope = s; } - Scope::LateBoundary { s, what } => { - crossed_late_boundary = Some(what); + Scope::LateBoundary { s, what, deny_late_regions } => { + if deny_late_regions { + crossed_late_boundary = Some(what); + } scope = s; } } @@ -1508,7 +1515,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { scope = s; } - Scope::LateBoundary { s, what } => { + Scope::LateBoundary { s, what, deny_late_regions: _ } => { crossed_late_boundary = Some(what); scope = s; } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 3e01f0512c46..9a5cf9d4e84f 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -4,8 +4,8 @@ use rustc_middle::mir::{ self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, }; -use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, SwitchIntTarget}; +use super::visitor::ResultsVisitor; +use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget}; pub trait Direction { const IS_FORWARD: bool; @@ -33,14 +33,14 @@ pub trait Direction { where A: Analysis<'tcx>; - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>; + A: Analysis<'tcx>; fn join_state_into_successors_of<'tcx, A>( analysis: &mut A, @@ -53,7 +53,7 @@ pub trait Direction { A: Analysis<'tcx>; } -/// Dataflow that runs from the exit of a block (the terminator), to its entry (the first statement). +/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement). pub struct Backward; impl Direction for Backward { @@ -157,32 +157,32 @@ impl Direction for Backward { analysis.apply_statement_effect(state, statement, location); } - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_end(state); // Terminator let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } @@ -389,32 +389,32 @@ impl Direction for Forward { } } - fn visit_results_in_block<'mir, 'tcx, F, R>( - state: &mut F, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = F>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = F>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_start(state); for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); vis.visit_block_end(state); diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index bac75b972f9b..98a4f58cb5dc 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -544,20 +544,18 @@ impl StateDiffCollector { } } -impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector +impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector where A: Analysis<'tcx>, A::Domain: DebugWithContext, { - type Domain = A::Domain; - - fn visit_block_start(&mut self, state: &Self::Domain) { + fn visit_block_start(&mut self, state: &A::Domain) { if A::Direction::IS_FORWARD { self.prev_state.clone_from(state); } } - fn visit_block_end(&mut self, state: &Self::Domain) { + fn visit_block_end(&mut self, state: &A::Domain) { if A::Direction::IS_BACKWARD { self.prev_state.clone_from(state); } @@ -566,7 +564,7 @@ where fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -579,7 +577,7 @@ where fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -590,7 +588,7 @@ where fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { @@ -603,7 +601,7 @@ where fn visit_terminator_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 8f81da8bb049..244dfe26ad36 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -55,8 +55,8 @@ mod visitor; pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; -pub use self::results::Results; -pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results}; +pub use self::results::{EntrySets, Results}; +pub use self::visitor::{ResultsVisitor, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds /// operations needed by all of them. diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 366fcbf33ba3..ff6cafbfbaee 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -18,7 +18,7 @@ use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; -type EntrySets<'tcx, A> = IndexVec>::Domain>; +pub type EntrySets<'tcx, A> = IndexVec>::Domain>; /// A dataflow analysis that has converged to fixpoint. #[derive(Clone)] @@ -27,7 +27,7 @@ where A: Analysis<'tcx>, { pub analysis: A, - pub(super) entry_sets: EntrySets<'tcx, A>, + pub entry_sets: EntrySets<'tcx, A>, } impl<'tcx, A> Results<'tcx, A> @@ -51,7 +51,7 @@ where &mut self, body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { visit_results(body, blocks, self, vis) } @@ -59,7 +59,7 @@ where pub fn visit_reachable_with<'mir>( &mut self, body: &'mir mir::Body<'tcx>, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 3d6b008a6846..5c7539eed4d6 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -4,15 +4,15 @@ use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. -pub fn visit_results<'mir, 'tcx, D, R>( +pub fn visit_results<'mir, 'tcx, A>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - let mut state = results.bottom_value(body); + let mut state = results.analysis.bottom_value(body); #[cfg(debug_assertions)] let reachable_blocks = mir::traversal::reachable_as_bitset(body); @@ -22,23 +22,23 @@ pub fn visit_results<'mir, 'tcx, D, R>( assert!(reachable_blocks.contains(block)); let block_data = &body[block]; - R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); + A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); } } -/// A visitor over the results of an `Analysis`. The type parameter `R` is the results type being -/// visited. -pub trait ResultsVisitor<'mir, 'tcx, R> { - type Domain; - - fn visit_block_start(&mut self, _state: &Self::Domain) {} +/// A visitor over the results of an `Analysis`. +pub trait ResultsVisitor<'mir, 'tcx, A> +where + A: Analysis<'tcx>, +{ + fn visit_block_start(&mut self, _state: &A::Domain) {} /// Called with the `before_statement_effect` of the given statement applied to `state` but not /// its `statement_effect`. fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { @@ -48,19 +48,19 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// statement applied to `state`. fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { } - /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not - /// its `terminator_effect`. + /// Called with the `before_terminator_effect` of the given terminator applied to `state` but + /// not its `terminator_effect`. fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { @@ -72,109 +72,12 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// The `call_return_effect` (if one exists) will *not* be applied to `state`. fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { } - fn visit_block_end(&mut self, _state: &Self::Domain) {} -} - -/// Things that can be visited by a `ResultsVisitor`. -/// -/// This trait exists so that we can visit the results of one or more dataflow analyses -/// simultaneously. -pub trait ResultsVisitable<'tcx> { - type Direction: Direction; - type Domain; - - /// Creates an empty `Domain` to hold the transient state for these dataflow results. - /// - /// The value of the newly created `Domain` will be overwritten by `reset_to_block_entry` - /// before it can be observed by a `ResultsVisitor`. - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain; - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock); - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); -} - -impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A> -where - A: Analysis<'tcx>, -{ - type Domain = A::Domain; - type Direction = A::Direction; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - self.analysis.bottom_value(body) - } - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) { - state.clone_from(self.entry_set_for_block(block)); - } - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_statement_effect(state, stmt, loc); - } - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_statement_effect(state, stmt, loc); - } - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_terminator_effect(state, term, loc); - } - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_terminator_effect(state, term, loc); - } + fn visit_block_end(&mut self, _state: &A::Domain) {} } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b404e3bfb72c..ab1453f1ed09 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,8 +18,8 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results, - ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, + Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable, + Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, visit_results, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 73abb669a111..10f1e0098550 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -3,7 +3,7 @@ use rustc_index::interval::SparseIntervalMatrix; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, BasicBlock, Body, Location}; -use crate::framework::{ResultsVisitable, ResultsVisitor, visit_results}; +use crate::framework::{Analysis, Results, ResultsVisitor, visit_results}; /// Maps between a `Location` and a `PointIndex` (and vice versa). pub struct DenseLocationMap { @@ -95,14 +95,14 @@ rustc_index::newtype_index! { } /// Add points depending on the result of the given dataflow analysis. -pub fn save_as_intervals<'tcx, N, R>( +pub fn save_as_intervals<'tcx, N, A>( elements: &DenseLocationMap, body: &mir::Body<'tcx>, - mut results: R, + mut results: Results<'tcx, A>, ) -> SparseIntervalMatrix where N: Idx, - R: ResultsVisitable<'tcx, Domain = BitSet>, + A: Analysis<'tcx, Domain = BitSet>, { let values = SparseIntervalMatrix::new(elements.num_points()); let mut visitor = Visitor { elements, values }; @@ -120,16 +120,15 @@ struct Visitor<'a, N: Idx> { values: SparseIntervalMatrix, } -impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N> +impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N> where + A: Analysis<'tcx, Domain = BitSet>, N: Idx, { - type Domain = BitSet; - fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, location: Location, ) { @@ -142,8 +141,8 @@ where fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 063f220501f8..c2666caa1e87 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -68,11 +68,11 @@ use rustc_middle::ty::{ self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, }; use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; @@ -817,9 +817,9 @@ impl ops::Deref for CoroutineSavedLocals { /// computation; see `CoroutineLayout` for more. fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, - saved_locals: &CoroutineSavedLocals, + saved_locals: &'mir CoroutineSavedLocals, always_live_locals: BitSet, - mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, + mut requires_storage: Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -877,15 +877,13 @@ struct StorageConflictVisitor<'a, 'tcx> { eligible_storage_live: BitSet, } -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>> for StorageConflictVisitor<'a, 'tcx> { - type Domain = BitSet; - fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _statement: &'a Statement<'tcx>, loc: Location, ) { @@ -894,8 +892,8 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _terminator: &'a Terminator<'tcx>, loc: Location, ) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7d073f1fa579..ab6460c490b8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -941,16 +941,12 @@ fn try_write_constant<'tcx>( interp_ok(()) } -impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx>>> - for Collector<'_, 'tcx> -{ - type Domain = State>; - +impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> { #[instrument(level = "trace", skip(self, results, statement))] fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -972,7 +968,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -997,7 +993,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, terminator: &'mir Terminator<'tcx>, location: Location, ) { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index bdf940a04b56..293cee500bbd 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1324,7 +1324,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // This way they can use `macro_rules` defined later. self.visit_vis(&item.vis); self.visit_ident(&item.ident); - item.kind.walk(item, AssocCtxt::Trait, self); + item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self); visit::walk_list!(self, visit_attribute, &item.attrs); } _ => visit::walk_item(self, item), diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 72e34e5faf5a..c87a6439ec3e 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3535,7 +3535,6 @@ pub(crate) macro const_eval_select { /// In other words, the following code has *Undefined Behavior*: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::hint::unreachable_unchecked; @@ -3548,7 +3547,6 @@ pub(crate) macro const_eval_select { /// may panic, or it may not: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3581,7 +3579,6 @@ pub(crate) macro const_eval_select { /// behave identically: /// /// ``` -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3598,7 +3595,11 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] +#[cfg_attr( + bootstrap, + rustc_const_stable(feature = "const_is_val_statically_known", since = "CURRENT_RUSTC_VERSION") +)] +#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6f7ea7694207..0ce33958941c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -139,7 +139,6 @@ #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] -#![feature(is_val_statically_known)] #![feature(lazy_get)] #![feature(link_cfg)] #![feature(non_null_from_ref)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 4d24b1020960..318bb8ee4cda 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2242,7 +2242,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2808,7 +2807,6 @@ macro_rules! int_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0a5101884f7d..0383c13fa082 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2251,7 +2251,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2791,7 +2790,6 @@ macro_rules! uint_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 93b4ad5c1c94..7f2a5424787f 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -469,7 +469,7 @@ impl AtomicBool { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -1264,7 +1264,7 @@ impl AtomicPtr { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -2263,7 +2263,7 @@ macro_rules! atomic_int { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6d118ae57843..c1a021e9f8d9 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -692,8 +692,6 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { const quadcolon = /::\s*::/.exec(path); if (path.startsWith("::")) { throw ["Paths cannot start with ", "::"]; - } else if (path.endsWith("::")) { - throw ["Paths cannot end with ", "::"]; } else if (quadcolon !== null) { throw ["Unexpected ", quadcolon[0]]; } @@ -3974,18 +3972,19 @@ class DocSearch { if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) { const elem = parsedQuery.elems[0]; - for (const id of this.nameTrie.search(elem.normalizedPathLast, this.tailTable)) { + // use arrow functions to preserve `this`. + const handleNameSearch = id => { const row = this.searchIndex[id]; if (!typePassesFilter(elem.typeFilter, row.ty) || (filterCrates !== null && row.crate !== filterCrates)) { - continue; + return; } let pathDist = 0; if (elem.fullPath.length > 1) { pathDist = checkPath(elem.pathWithoutLast, row); if (pathDist === null) { - continue; + return; } } @@ -4008,9 +4007,20 @@ class DocSearch { maxEditDistance, ); } + }; + if (elem.normalizedPathLast !== "") { + const last = elem.normalizedPathLast; + for (const id of this.nameTrie.search(last, this.tailTable)) { + handleNameSearch(id); + } } const length = this.searchIndex.length; + for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) { + // queries that end in :: bypass the trie + if (elem.normalizedPathLast === "") { + handleNameSearch(i); + } const row = this.searchIndex[i]; if (filterCrates !== null && row.crate !== filterCrates) { continue; diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 327a547b2959..68c481bda6e1 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3449,21 +3449,14 @@ impl Rewrite for ast::ForeignItem { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span.lo(); let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - self.ident, - sig, - &self.vis, - generics, - Some(body), - ), + visit::FnKind::Fn(fn_ctxt, &self.ident, sig, &self.vis, generics, body), &sig.decl, self.span, defaultness, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 8102fe7ad8f2..9b116b620b79 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -390,7 +390,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { block = b; self.rewrite_fn_before_block( indent, - ident, + *ident, &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), ) @@ -540,21 +540,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let inner_attrs = inner_attributes(&item.attrs); let fn_ctxt = match sig.header.ext { ast::Extern::None => visit::FnCtxt::Free, _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - item.ident, - sig, - &item.vis, - generics, - Some(body), - ), + visit::FnKind::Fn(fn_ctxt, &item.ident, sig, &item.vis, generics, body), &sig.decl, item.span, defaultness, @@ -648,11 +641,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let inner_attrs = inner_attributes(&ai.attrs); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)), + visit::FnKind::Fn(fn_ctxt, &ai.ident, sig, &ai.vis, generics, body), &sig.decl, ai.span, defaultness, diff --git a/tests/crashes/131535.rs b/tests/crashes/131535.rs deleted file mode 100644 index 47ccdf87f2de..000000000000 --- a/tests/crashes/131535.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #131535 -#![feature(non_lifetime_binders)] -trait v0<> {} -fn kind :(v0<'_, > impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/131637.rs b/tests/crashes/131637.rs deleted file mode 100644 index 7d328384a745..000000000000 --- a/tests/crashes/131637.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #121637 -#![feature(non_lifetime_binders)] -trait Trait { - type Type; - - fn method(&self) -> impl for Trait>; -} diff --git a/tests/crashes/132530.rs b/tests/crashes/132530.rs deleted file mode 100644 index b43da62bfc11..000000000000 --- a/tests/crashes/132530.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #132530 - -#![feature(non_lifetime_binders)] - -trait Trait<'a, A> { - type Assoc<'a> = i32; -} - -fn a() -> impl for Trait> {} diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index 068298e72360..8bffef61c8f4 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -143,14 +143,6 @@ const PARSED = [ returned: [], error: "Unexpected `:: ::`", }, - { - query: "a::b::", - elems: [], - foundElems: 0, - userQuery: "a::b::", - returned: [], - error: "Paths cannot end with `::`", - }, { query: ":a", elems: [], diff --git a/tests/rustdoc-js-std/path-end-empty.js b/tests/rustdoc-js-std/path-end-empty.js new file mode 100644 index 000000000000..6e853c61b4d9 --- /dev/null +++ b/tests/rustdoc-js-std/path-end-empty.js @@ -0,0 +1,6 @@ +const EXPECTED = { + 'query': 'Option::', + 'others': [ + { 'path': 'std::option::Option', 'name': 'get_or_insert_default' }, + ], +} diff --git a/tests/ui/consts/is_val_statically_known.rs b/tests/ui/consts/is_val_statically_known.rs index a9059817bcc5..d55910d32d33 100644 --- a/tests/ui/consts/is_val_statically_known.rs +++ b/tests/ui/consts/is_val_statically_known.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(core_intrinsics, is_val_statically_known)] +#![feature(core_intrinsics)] use std::intrinsics::is_val_statically_known; diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs index dda42580e0f3..2a3017885255 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs @@ -7,6 +7,7 @@ fn produce() -> impl for Trait<(), Assoc = impl Trait> { //~^ ERROR associated type `Assoc` not found for `Trait` //~| ERROR associated type `Assoc` not found for `Trait` //~| the trait bound `{integer}: Trait<()>` is not satisfied + //~| ERROR cannot capture late-bound type parameter in nested `impl Trait` 16 } diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr index 6e5bd34ce381..38dcdbd0af2a 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr @@ -1,3 +1,9 @@ +error: cannot capture late-bound type parameter in nested `impl Trait` + --> $DIR/non-lifetime-binder-in-constraint.rs:6:58 + | +LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { + | - parameter defined here ^ + error[E0220]: associated type `Assoc` not found for `Trait` --> $DIR/non-lifetime-binder-in-constraint.rs:6:39 | @@ -27,7 +33,7 @@ help: this trait has no implementations, consider adding one LL | trait Trait {} | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0220, E0277. For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs index 23951c342700..23f3666618bf 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs @@ -5,6 +5,7 @@ trait Trait {} fn f() -> impl for Trait> {} //~^ ERROR nested `impl Trait` is not allowed -//~| ERROR the trait bound `(): Trait>` is not satisfied +//~| ERROR the trait bound `(): Trait>` is not satisfied +//~| ERROR cannot capture late-bound type parameter in nested `impl Trait` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr index 5859d952b75c..3c352c9889cf 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr @@ -7,11 +7,19 @@ LL | fn f() -> impl for Trait> {} | | nested `impl Trait` here | outer `impl Trait` -error[E0277]: the trait bound `(): Trait>` is not satisfied +error: cannot capture late-bound type parameter in nested `impl Trait` + --> $DIR/non-lifetime-binder.rs:6:40 + | +LL | fn f() -> impl for Trait> {} + | - ^ + | | + | parameter defined here + +error[E0277]: the trait bound `(): Trait>` is not satisfied --> $DIR/non-lifetime-binder.rs:6:11 | LL | fn f() -> impl for Trait> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait>` is not implemented for `()` | help: this trait has no implementations, consider adding one --> $DIR/non-lifetime-binder.rs:4:1 @@ -19,7 +27,7 @@ help: this trait has no implementations, consider adding one LL | trait Trait {} | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0666. For more information about an error, try `rustc --explain E0277`. diff --git a/triagebot.toml b/triagebot.toml index d5bc549ca9ff..c5942fe27cdd 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -997,7 +997,6 @@ compiler = [ "@oli-obk", "@petrochenkov", "@pnkfelix", - "@TaKO8Ki", "@wesleywiser", ] libs = [ @@ -1048,7 +1047,6 @@ diagnostics = [ "@davidtwco", "@estebank", "@oli-obk", - "@TaKO8Ki", "@chenyukang", ] parser = [