diff options
Diffstat (limited to 'compiler')
138 files changed, 1726 insertions, 1665 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 80caf37d709..9a6d12faa60 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -9,6 +9,7 @@ use crate::token::{self, CommentKind, Token}; use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing}; use crate::tokenstream::{LazyTokenStream, TokenStream}; +use crate::util::comments; use rustc_index::bit_set::GrowableBitSet; use rustc_span::source_map::BytePos; @@ -262,6 +263,10 @@ impl Attribute { } } + pub fn may_have_doc_links(&self) -> bool { + self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str())) + } + pub fn get_normal_item(&self) -> &AttrItem { match self.kind { AttrKind::Normal(ref item, _) => item, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index affb4289cb1..d609fa67205 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -94,16 +94,6 @@ impl TokenTree { TokenTree::Token(Token::new(kind, span)) } - /// Returns the opening delimiter as a token tree. - pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { - TokenTree::token(token::OpenDelim(delim), span.open) - } - - /// Returns the closing delimiter as a token tree. - pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { - TokenTree::token(token::CloseDelim(delim), span.close) - } - pub fn uninterpolate(self) -> TokenTree { match self { TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()), @@ -585,13 +575,20 @@ impl Cursor { Cursor { stream, index: 0 } } + #[inline] pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> { - if self.index < self.stream.len() { + self.stream.0.get(self.index).map(|tree| { self.index += 1; - Some(self.stream.0[self.index - 1].clone()) - } else { - None - } + tree.clone() + }) + } + + #[inline] + pub fn next_with_spacing_ref(&mut self) -> Option<&TreeAndSpacing> { + self.stream.0.get(self.index).map(|tree| { + self.index += 1; + tree + }) } pub fn index(&self) -> usize { diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 8730aeb0f3b..b4fff0022e2 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -24,6 +24,14 @@ pub struct Comment { pub pos: BytePos, } +/// A fast conservative estimate on whether the string can contain documentation links. +/// A pair of square brackets `[]` must exist in the string, but we only search for the +/// opening bracket because brackets always go in pairs in practice. +#[inline] +pub fn may_have_doc_links(s: &str) -> bool { + s.contains('[') +} + /// Makes a doc string more presentable to users. /// Used by rustdoc and perhaps other tools, but not by rustc. pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 5eab21bf79a..0f90239f4c8 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -290,18 +290,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime)); } - fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) { - match visibility.node { - VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} - VisibilityKind::Restricted { hir_id, .. } => { - self.insert(visibility.span, hir_id, Node::Visibility(visibility)); - self.with_parent(hir_id, |this| { - intravisit::walk_vis(this, visibility); - }); - } - } - } - fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) { self.insert(v.span, v.id, Node::Variant(v)); self.with_parent(v.id, |this| { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a8bd8c92a41..29353d47b87 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -14,7 +14,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::utils::NtToTokenstream; use rustc_session::Session; -use rustc_span::source_map::{respan, DesugaringKind}; +use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; @@ -230,15 +230,15 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let mut ident = i.ident; - let mut vis = self.lower_visibility(&i.vis); + let vis_span = self.lower_span(i.vis.span); let hir_id = self.lower_node_id(i.id); let attrs = self.lower_attrs(hir_id, &i.attrs); - let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); let item = hir::Item { def_id: hir_id.expect_owner(), ident: self.lower_ident(ident), kind, - vis, + vis_span, span: self.lower_span(i.span), }; self.arena.alloc(item) @@ -251,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: hir::HirId, ident: &mut Ident, attrs: Option<&'hir [Attribute]>, - vis: &mut hir::Visibility<'hir>, + vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { match *i { @@ -260,7 +260,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Start with an empty prefix. let prefix = Path { segments: vec![], span: use_tree.span, tokens: None }; - self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) + self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); @@ -527,12 +527,11 @@ impl<'hir> LoweringContext<'_, 'hir> { tree: &UseTree, prefix: &Path, id: NodeId, - vis: &mut hir::Visibility<'hir>, + vis_span: Span, ident: &mut Ident, attrs: Option<&'hir [Attribute]>, ) -> hir::ItemKind<'hir> { debug!("lower_use_tree(tree={:?})", tree); - debug!("lower_use_tree: vis = {:?}", vis); let path = &tree.prefix; let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect(); @@ -586,7 +585,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = this.lower_res(res); let path = this.lower_path_extra(res, &path, ParamMode::Explicit); let kind = hir::ItemKind::Use(path, hir::UseKind::Single); - let vis = this.rebuild_vis(&vis); if let Some(attrs) = attrs { this.attrs.insert(hir::ItemLocalId::new(0), attrs); } @@ -595,7 +593,7 @@ impl<'hir> LoweringContext<'_, 'hir> { def_id: new_id, ident: this.lower_ident(ident), kind, - vis, + vis_span, span: this.lower_span(span), }; hir::OwnerNode::Item(this.arena.alloc(item)) @@ -657,11 +655,10 @@ impl<'hir> LoweringContext<'_, 'hir> { // own its own names, we have to adjust the owner before // lowering the rest of the import. self.with_hir_id_owner(id, |this| { - let mut vis = this.rebuild_vis(&vis); let mut ident = *ident; let kind = - this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs); + this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs); if let Some(attrs) = attrs { this.attrs.insert(hir::ItemLocalId::new(0), attrs); } @@ -670,37 +667,13 @@ impl<'hir> LoweringContext<'_, 'hir> { def_id: new_hir_id, ident: this.lower_ident(ident), kind, - vis, + vis_span, span: this.lower_span(use_tree.span), }; hir::OwnerNode::Item(this.arena.alloc(item)) }); } - // Subtle and a bit hacky: we lower the privacy level - // of the list stem to "private" most of the time, but - // not for "restricted" paths. The key thing is that - // we don't want it to stay as `pub` (with no caveats) - // because that affects rustdoc and also the lints - // about `pub` items. But we can't *always* make it - // private -- particularly not for restricted paths -- - // because it contains node-ids that would then be - // unused, failing the check that HirIds are "densely - // assigned". - match vis.node { - hir::VisibilityKind::Public - | hir::VisibilityKind::Crate(_) - | hir::VisibilityKind::Inherited => { - *vis = respan( - self.lower_span(prefix.span.shrink_to_lo()), - hir::VisibilityKind::Inherited, - ); - } - hir::VisibilityKind::Restricted { .. } => { - // Do nothing here, as described in the comment on the match. - } - } - let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err); let res = self.lower_res(res); let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit); @@ -709,37 +682,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated - /// many times in the HIR tree; for each occurrence, we need to assign distinct - /// `NodeId`s. (See, e.g., #56128.) - fn rebuild_use_path(&mut self, path: &hir::Path<'hir>) -> &'hir hir::Path<'hir> { - debug!("rebuild_use_path(path = {:?})", path); - let segments = - self.arena.alloc_from_iter(path.segments.iter().map(|seg| hir::PathSegment { - ident: seg.ident, - hir_id: seg.hir_id.map(|_| self.next_id()), - res: seg.res, - args: None, - infer_args: seg.infer_args, - })); - self.arena.alloc(hir::Path { span: path.span, res: path.res, segments }) - } - - fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir> { - let vis_kind = match vis.node { - hir::VisibilityKind::Public => hir::VisibilityKind::Public, - hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), - hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - hir::VisibilityKind::Restricted { ref path, hir_id: _ } => { - hir::VisibilityKind::Restricted { - path: self.rebuild_use_path(path), - hir_id: self.next_id(), - } - } - }; - respan(self.lower_span(vis.span), vis_kind) - } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let def_id = hir_id.expect_owner(); @@ -773,7 +715,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), }, - vis: self.lower_visibility(&i.vis), + vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), }; self.arena.alloc(item) @@ -851,7 +793,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(jseyfried): positional field hygiene. None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, - vis: self.lower_visibility(&f.vis), + vis_span: self.lower_span(f.vis.span), ty, } } @@ -1016,8 +958,8 @@ impl<'hir> LoweringContext<'_, 'hir> { def_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), generics, - vis: self.lower_visibility(&i.vis), kind, + vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), }; self.arena.alloc(item) @@ -1044,28 +986,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - /// If an `explicit_owner` is given, this method allocates the `HirId` in - /// the address space of that item instead of the item currently being - /// lowered. This can happen during `lower_impl_item_ref()` where we need to - /// lower a `Visibility` value although we haven't lowered the owning - /// `ImplItem` in question yet. - fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> { - let node = match v.kind { - VisibilityKind::Public => hir::VisibilityKind::Public, - VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), - VisibilityKind::Restricted { ref path, id } => { - debug!("lower_visibility: restricted path id = {:?}", id); - let lowered_id = self.lower_node_id(id); - hir::VisibilityKind::Restricted { - path: self.lower_path(id, path, ParamMode::Explicit), - hir_id: lowered_id, - } - } - VisibilityKind::Inherited => hir::VisibilityKind::Inherited, - }; - respan(self.lower_span(v.span), node) - } - fn lower_defaultness( &self, d: Defaultness, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9cb205074e7..b15f299b5f2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -61,7 +61,7 @@ use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, MacroKind}; -use rustc_span::source_map::{respan, DesugaringKind}; +use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -1530,7 +1530,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id: opaque_ty_id, ident: Ident::empty(), kind: opaque_ty_item_kind, - vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited), + vis_span: self.lower_span(span.shrink_to_lo()), span: self.lower_span(opaque_ty_span), }; hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index cb9e0234c49..c19a39c393f 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -156,6 +156,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> { sup: self.static_region, sub: next_static_idx.into(), locations: Locations::All(DUMMY_SP), + span: DUMMY_SP, category: ConstraintCategory::Internal, variance_info: VarianceDiagInfo::default(), }) @@ -189,7 +190,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> { /// Given a region `R`, iterate over all regions `R1` such that /// there exists a constraint `R: R1`. - crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, 'tcx, D> { + crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'s, 'tcx, D> { Successors { edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region), } @@ -224,10 +225,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph } } -impl<'s, 'graph, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph> - for RegionGraph<'s, 'tcx, D> -{ +impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'_> for RegionGraph<'s, 'tcx, D> { type Item = RegionVid; - // FIXME - why can't this be `'graph, 'tcx` - type Iter = Successors<'graph, 'graph, D>; + type Iter = Successors<'s, 'tcx, D>; } diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index d41143ee763..14f0e5f620a 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -2,6 +2,7 @@ use rustc_data_structures::graph::scc::Sccs; use rustc_index::vec::IndexVec; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; +use rustc_span::Span; use std::fmt; use std::ops::Index; @@ -87,6 +88,12 @@ pub struct OutlivesConstraint<'tcx> { /// Where did this constraint arise? pub locations: Locations, + /// The `Span` associated with the creation of this constraint. + /// This should be used in preference to obtaining the span from + /// `locations`, since the `locations` may give a poor span + /// in some cases (e.g. converting a constraint from a promoted). + pub span: Span, + /// What caused this constraint? pub category: ConstraintCategory, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9e5fb674772..3b4e9e95b0e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; +use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, @@ -22,6 +23,7 @@ use rustc_trait_selection::traits::TraitEngineExt as _; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; +use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::find_all_local_uses; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, @@ -1484,7 +1486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion_hidden( return_span, "use `.collect()` to allocate the iterator", - format!("{}{}", snippet, ".collect::<Vec<_>>()"), + format!("{snippet}.collect::<Vec<_>>()"), Applicability::MaybeIncorrect, ); } @@ -1956,45 +1958,46 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> { let tcx = self.infcx.tcx; - match place.last_projection() { - None => StorageDeadOrDrop::LocalStorageDead, - Some((place_base, elem)) => { - // FIXME(spastorino) make this iterate - let base_access = self.classify_drop_access_kind(place_base); - match elem { - ProjectionElem::Deref => match base_access { - StorageDeadOrDrop::LocalStorageDead - | StorageDeadOrDrop::BoxedStorageDead => { - assert!( - place_base.ty(self.body, tcx).ty.is_box(), - "Drop of value behind a reference or raw pointer" - ); - StorageDeadOrDrop::BoxedStorageDead - } - StorageDeadOrDrop::Destructor(_) => base_access, - }, - ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = place_base.ty(self.body, tcx).ty; - match base_ty.kind() { - ty::Adt(def, _) if def.has_dtor(tcx) => { - // Report the outermost adt with a destructor - match base_access { - StorageDeadOrDrop::Destructor(_) => base_access, - StorageDeadOrDrop::LocalStorageDead - | StorageDeadOrDrop::BoxedStorageDead => { - StorageDeadOrDrop::Destructor(base_ty) + let (kind, _place_ty) = place.projection.iter().fold( + (LocalStorageDead, PlaceTy::from_ty(self.body.local_decls[place.local].ty)), + |(kind, place_ty), &elem| { + ( + match elem { + ProjectionElem::Deref => match kind { + StorageDeadOrDrop::LocalStorageDead + | StorageDeadOrDrop::BoxedStorageDead => { + assert!( + place_ty.ty.is_box(), + "Drop of value behind a reference or raw pointer" + ); + StorageDeadOrDrop::BoxedStorageDead + } + StorageDeadOrDrop::Destructor(_) => kind, + }, + ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { + match place_ty.ty.kind() { + ty::Adt(def, _) if def.has_dtor(tcx) => { + // Report the outermost adt with a destructor + match kind { + StorageDeadOrDrop::Destructor(_) => kind, + StorageDeadOrDrop::LocalStorageDead + | StorageDeadOrDrop::BoxedStorageDead => { + StorageDeadOrDrop::Destructor(place_ty.ty) + } } } + _ => kind, } - _ => base_access, } - } - ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::Index(_) => base_access, - } - } - } + ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Index(_) => kind, + }, + place_ty.projection_ty(tcx, elem), + ) + }, + ); + kind } /// Describe the reason for the fake borrow that was assigned to `place`. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 5fd9ecf4513..fd78b483b75 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -4,6 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_infer::infer::{ error_reporting::nice_region_error::NiceRegionError, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, + RelateParamBound, }; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; @@ -166,11 +167,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let type_test_span = type_test.locations.span(&self.body); if let Some(lower_bound_region) = lower_bound_region { + let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); + let origin = RelateParamBound(type_test_span, generic_ty, None); self.buffer_error(self.infcx.construct_generic_bound_failure( type_test_span, - None, + Some(origin), type_test.generic_kind, lower_bound_region, + self.body.source.def_id().as_local(), )); } else { // FIXME. We should handle this case better. It diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 97233b930c3..fe5193102f9 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -74,14 +74,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); for constraint in &constraints { - let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint; + let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } = + constraint; let (name, arg) = match locations { Locations::All(span) => { ("All", tcx.sess.source_map().span_to_embeddable_string(*span)) } Locations::Single(loc) => ("Single", format!("{:?}", loc)), }; - with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?; + with_msg(&format!( + "{:?}: {:?} due to {:?} at {}({}) ({:?}", + sup, sub, category, name, arg, span + ))?; } Ok(()) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index dabf61715ce..cf03f34a4ec 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1733,7 +1733,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { crate fn retrieve_closure_constraint_info( &self, - body: &Body<'tcx>, + _body: &Body<'tcx>, constraint: &OutlivesConstraint<'tcx>, ) -> BlameConstraint<'tcx> { let loc = match constraint.locations { @@ -1760,7 +1760,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .unwrap_or(BlameConstraint { category: constraint.category, from_closure: false, - cause: ObligationCause::dummy_with_span(body.source_info(loc).span), + cause: ObligationCause::dummy_with_span(constraint.span), variance_info: constraint.variance_info, }) } @@ -1869,6 +1869,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { sup: r, sub: constraint.min_choice, locations: Locations::All(p_c.definition_span), + span: p_c.definition_span, category: ConstraintCategory::OpaqueType, variance_info: ty::VarianceDiagInfo::default(), }; @@ -2017,7 +2018,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { category: constraint.category, from_closure: false, cause: ObligationCause::new( - constraint.locations.span(body), + constraint.span, CRATE_HIR_ID, cause_code.clone(), ), diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 5022cb98b82..21190a850b7 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::DUMMY_SP; +use rustc_span::{Span, DUMMY_SP}; use crate::{ constraints::OutlivesConstraint, @@ -26,6 +26,7 @@ crate struct ConstraintConversion<'a, 'tcx> { implicit_region_bound: Option<ty::Region<'tcx>>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + span: Span, category: ConstraintCategory, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -38,6 +39,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { implicit_region_bound: Option<ty::Region<'tcx>>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + span: Span, category: ConstraintCategory, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { @@ -49,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { implicit_region_bound, param_env, locations, + span, category, constraints, } @@ -153,6 +156,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { self.constraints.outlives_constraints.push(OutlivesConstraint { locations: self.locations, category: self.category, + span: self.span, sub, sup, variance_info: ty::VarianceDiagInfo::default(), diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f8439d2e163..f08f2e1b12d 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -316,6 +316,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.implicit_region_bound, self.param_env, Locations::All(DUMMY_SP), + DUMMY_SP, ConstraintCategory::Internal, &mut self.constraints, ) diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 83c8ecba1f1..e6f996491a4 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -235,6 +235,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(self.implicit_region_bound), self.param_env, Locations::All(DUMMY_SP), + DUMMY_SP, ConstraintCategory::Internal, &mut self.borrowck_context.constraints, ) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ece801716b2..6dcdd46816e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1141,6 +1141,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(self.implicit_region_bound), self.param_env, locations, + locations.span(self.body), category, &mut self.borrowck_context.constraints, ) @@ -2401,6 +2402,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sup: ref_region.to_region_vid(), sub: borrow_region.to_region_vid(), locations: location.to_locations(), + span: location.to_locations().span(body), category, variance_info: ty::VarianceDiagInfo::default(), }); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f0106630797..f98d2c3128c 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -116,6 +116,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> sup, sub, locations: self.locations, + span: self.locations.span(self.type_checker.body), category: self.category, variance_info: info, }, diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 30e9627c48d..7b8e43b639f 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -33,18 +33,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16922317bd7dd104d509a373887822caa0242fc1def00de66abb538db221db4" +checksum = "ed44413e7e2fe3260d0ed73e6956ab188b69c10ee92b892e401e0f4f6808c68b" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b80bf40380256307b68a3dcbe1b91cac92a533e212b5b635abc3e4525781a0a" +checksum = "0b5d83f0f26bf213f971f45589d17e5b65e4861f9ed22392b0cbb6eaa5bd329c" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -59,30 +59,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d0ed7d3bc6c7a814ca12858175bf4e93167a3584127858c686e4b5dd6e432" +checksum = "6800dc386177df6ecc5a32680607ed8ba1fa0d31a2a59c8c61fbf44826b8191d" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f52311e1c90de12dcf8c4b9999c6ebfd1ed360373e88c357160936844511f6" +checksum = "c961f85070985ebc8fcdb81b838a5cf842294d1e6ed4852446161c7e246fd455" [[package]] name = "cranelift-entity" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bc82ef522c1f643baf7d4d40b7c52643ee4549d8960b0e6a047daacb83f897" +checksum = "2347b2b8d1d5429213668f2a8e36c85ee3c73984a2f6a79007e365d3e575e7ed" [[package]] name = "cranelift-frontend" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc35e4251864b17515845ba47447bca88fec9ca1a4186b19fe42526e36140e8" +checksum = "4cbcdbf7bed29e363568b778649b69dabc3d727256d5d25236096ef693757654" dependencies = [ "cranelift-codegen", "log", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c66d594ad3bfe4e58b1fbd8d17877a7c6564a5f2d6f78cbbf4b0182af1927f" +checksum = "7c769d4e0d76f59c8b2a3bf0477d89ee149bb0731b53fbb245ee081d49063095" dependencies = [ "anyhow", "cranelift-codegen", @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf356697c40232aa09e1e3fb8a350ee894e849ccecc4eac56ff0570a4575c325" +checksum = "0ab57d399a2401074bb0cc40b3031e420f3d66d46ec0cf21eeae53ac04bd73e2" dependencies = [ "anyhow", "cranelift-codegen", @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b882b2251c9845d509d92aebfdb6c8bb3b3b48e207ac951f21fbd20cfe7f90b3" +checksum = "8f4cdf93552e5ceb2e3c042829ebb4de4378492705f769eadc6a7c6c5251624c" dependencies = [ "cranelift-codegen", "libc", @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.82.1" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3f1a88e654e567d2591169239ed157ab290811a729a6468f53999c01001263" +checksum = "cf8e65f4839c26e6237fc0744911d79b0a2ac5e76b4e4eebd14db2b8d849fd31" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 70c03da3f29..74f50808a98 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.82.1", features = ["unwind", "all-arch"] } -cranelift-frontend = "0.82.1" -cranelift-module = "0.82.1" -cranelift-native = "0.82.1" -cranelift-jit = { version = "0.82.1", optional = true } -cranelift-object = "0.82.1" +cranelift-codegen = { version = "0.83.0", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.83.0" +cranelift-module = "0.83.0" +cranelift-native = "0.83.0" +cranelift-jit = { version = "0.83.0", optional = true } +cranelift-object = "0.83.0" target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index f584f54e106..51ba0dbfcc7 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.71" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163437f05ca8f29d7e9128ea728dedf5eb620e445fbca273641d3a3050305f23" +checksum = "afdbb35d279238cf77f0c9e8d90ad50d6c7bff476ab342baafa29440f0f10bff" dependencies = [ "rustc-std-workspace-core", ] @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.121" +version = "0.2.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" dependencies = [ "rustc-std-workspace-core", ] @@ -203,6 +203,7 @@ dependencies = [ name = "proc_macro" version = "0.0.0" dependencies = [ + "core", "std", ] diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs new file mode 100644 index 00000000000..b8f901d1ba1 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs @@ -0,0 +1,53 @@ +// Copied from https://github.com/rust-lang/rust/blob/3fe3b89cd57229343eeca753fdd8c63d9b03c65c/src/test/ui/simd/intrinsic/float-minmax-pass.rs +// run-pass +// ignore-emscripten + +// Test that the simd_f{min,max} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fmin<T>(x: T, y: T) -> T; + fn simd_fmax<T>(x: T, y: T) -> T; +} + +fn main() { + let x = f32x4(1.0, 2.0, 3.0, 4.0); + let y = f32x4(2.0, 1.0, 4.0, 3.0); + + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + let nan = f32::NAN; + // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit. + // See https://github.com/rust-lang/rust/issues/52746. + #[cfg(any(target_arch = "mips", target_arch = "mips64"))] + let nan = f32::from_bits(f32::NAN.to_bits() - 1); + + let n = f32x4(nan, nan, nan, nan); + + unsafe { + let min0 = simd_fmin(x, y); + let min1 = simd_fmin(y, x); + assert_eq!(min0, min1); + let e = f32x4(1.0, 1.0, 3.0, 3.0); + assert_eq!(min0, e); + let minn = simd_fmin(x, n); + assert_eq!(minn, x); + let minn = simd_fmin(y, n); + assert_eq!(minn, y); + + let max0 = simd_fmax(x, y); + let max1 = simd_fmax(y, x); + assert_eq!(max0, max1); + let e = f32x4(2.0, 2.0, 4.0, 4.0); + assert_eq!(max0, e); + let maxn = simd_fmax(x, n); + assert_eq!(maxn, x); + let maxn = simd_fmax(y, n); + assert_eq!(maxn, y); + } +} diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 7efc8dc785a..8da705e0cb0 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -16,6 +16,9 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "destruct"] +pub trait Destruct {} + #[lang = "unsize"] pub trait Unsize<T: ?Sized> {} @@ -491,13 +494,20 @@ pub trait Deref { fn deref(&self) -> &Self::Target; } +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_nonnull_optimization_guaranteed] +pub struct NonNull<T: ?Sized>(pub *mut T); + +impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {} +impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {} + pub struct Unique<T: ?Sized> { - pub pointer: *const T, + pub pointer: NonNull<T>, pub _marker: PhantomData<T>, } impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {} - impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {} #[lang = "owned_box"] @@ -526,7 +536,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { #[lang = "box_free"] unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, alloc: ()) { - libc::free(ptr.pointer as *mut u8); + libc::free(ptr.pointer.0 as *mut u8); } #[lang = "drop"] diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index c4730581335..85ca908d0a2 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -122,7 +122,7 @@ fn call_return_u128_pair() { #[allow(unreachable_code)] // FIXME false positive fn main() { take_unique(Unique { - pointer: 0 as *const (), + pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData, }); take_f32(0.1); @@ -173,7 +173,7 @@ fn main() { assert!(intrinsics::needs_drop::<NoisyDrop>()); Unique { - pointer: 0 as *const &str, + pointer: NonNull(1 as *mut &str), _marker: PhantomData, } as Unique<dyn SomeTrait>; diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 5bc51a541b5..0a2bce2621d 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -1,7 +1,8 @@ -#![feature(core_intrinsics, generators, generator_trait, is_sorted)] +#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)] #[cfg(target_arch = "x86_64")] use std::arch::x86_64::*; +use std::hint::black_box; use std::io::Write; use std::ops::Generator; @@ -86,6 +87,9 @@ fn main() { assert_eq!(houndred_f64 as i128, 100); assert_eq!(1u128.rotate_left(2), 4); + assert_eq!(black_box(f32::NAN) as i128, 0); + assert_eq!(black_box(f32::NAN) as u128, 0); + // Test signed 128bit comparing let max = usize::MAX as i128; if 100i128 < 0i128 || 100i128 > max { diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch index c1325908691..54e13b090ab 100644 --- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch @@ -102,42 +102,6 @@ index 6a8ecd3..68fcb49 100644 } } } -diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs -index 31b7ee2..bd04b3c 100644 ---- a/crates/core_simd/tests/ops_macros.rs -+++ b/crates/core_simd/tests/ops_macros.rs -@@ -567,6 +567,7 @@ macro_rules! impl_float_tests { - }); - } - -+ /* - fn horizontal_max<const LANES: usize>() { - test_helpers::test_1(&|x| { - let vmax = Vector::<LANES>::from_array(x).horizontal_max(); -@@ -590,6 +591,7 @@ macro_rules! impl_float_tests { - Ok(()) - }); - } -+ */ - } - - #[cfg(feature = "std")] -@@ -604,6 +606,7 @@ macro_rules! impl_float_tests { - ) - } - -+ /* - fn mul_add<const LANES: usize>() { - test_helpers::test_ternary_elementwise( - &Vector::<LANES>::mul_add, -@@ -611,6 +614,7 @@ macro_rules! impl_float_tests { - &|_, _, _| true, - ) - } -+ */ - } - } - } -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 84d90e5db02..966097c248b 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-03-19" +channel = "nightly-2022-04-21" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index a0e99267c2b..f4e863e5494 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #![forbid(unsafe_code)]/* This line is ignored by bash # This block is ignored by rustc pushd $(dirname "$0")/../ diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 85c0109c6f6..cabbaaa8922 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e ./y.rs build --no-unstable-features diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index a32e6df2208..4cf24c02235 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e cd $(dirname "$0")/../ @@ -11,7 +11,7 @@ pushd rust command -v rg >/dev/null 2>&1 || cargo install ripgrep rm -r src/test/ui/{extern/,unsized-locals/,lto/,linkage*} || true -for test in $(rg --files-with-matches "asm!|lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do +for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do rm $test done @@ -25,14 +25,8 @@ git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR # ================ # requires stack unwinding -rm src/test/ui/backtrace.rs -rm src/test/ui/process/multi-panic.rs -rm src/test/ui/numbers-arithmetic/issue-8460.rs rm src/test/incremental/change_crate_dep_kind.rs rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101) -rm src/test/ui/panic-while-printing.rs -rm src/test/ui/test-attrs/test-panic-while-printing.rs -rm src/test/ui/test-attrs/test-type.rs # requires compiling with -Cpanic=unwind rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process" @@ -85,8 +79,6 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support # giving different but possibly correct results # ============================================= -rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result -rm src/test/ui/simd/intrinsic/float-minmax-pass.rs # same rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants rm src/test/ui/mir/mir_raw_fat_ptr.rs # same rm src/test/ui/consts/issue-33537.rs # same @@ -112,9 +104,14 @@ rm src/test/ui/mir/ssa-analysis-regression-50041.rs # produces ICE rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors +rm src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs # wrong result from `Location::caller()` + # bugs in the test suite # ====================== -rm src/test/ui/unsafe/union.rs # has UB caught by cg_clif. see rust-lang/rust#95075 +rm src/test/ui/backtrace.rs # TODO warning +rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support +rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support +rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout echo "[TEST] rustc test suite" RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental} diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh index fee1012c8f1..aae626081f6 100755 --- a/compiler/rustc_codegen_cranelift/scripts/tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/tests.sh @@ -72,6 +72,10 @@ function base_sysroot_tests() { $MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" $RUN_WRAPPER ./target/out/track-caller-attribute + echo "[AOT] float-minmax-pass" + $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" + $RUN_WRAPPER ./target/out/float-minmax-pass + echo "[AOT] mod_bench" $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE" $RUN_WRAPPER ./target/out/mod_bench diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 8c45993a8b7..65346cb3962 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -821,7 +821,8 @@ pub(crate) fn codegen_place<'tcx>( if cplace.layout().ty.is_box() { cplace = cplace .place_field(fx, Field::new(0)) // Box<T> -> Unique<T> - .place_field(fx, Field::new(0)) // Unique<T> -> *const T + .place_field(fx, Field::new(0)) // Unique<T> -> NonNull<T> + .place_field(fx, Field::new(0)) // NonNull<T> -> *mut T .place_deref(fx); } else { cplace = cplace.place_deref(fx); diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index e7e6afeb865..e19070774c6 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -84,7 +84,7 @@ pub(crate) fn clif_int_or_float_cast( fx.bcx.ins().fcvt_from_uint(to_ty, from) } } else if from_ty.is_float() && to_ty.is_int() { - if to_ty == types::I128 { + let val = if to_ty == types::I128 { // _____sssf___ // __fix sfti: f32 -> i128 // __fix dfti: f64 -> i128 @@ -109,13 +109,9 @@ pub(crate) fn clif_int_or_float_cast( let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - return fx - .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx); - } - - // float -> int-like - if to_ty == types::I8 || to_ty == types::I16 { + fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) + .load_scalar(fx) + } else if to_ty == types::I8 || to_ty == types::I16 { // FIXME implement fcvt_to_*int_sat.i8/i16 let val = if to_signed { fx.bcx.ins().fcvt_to_sint_sat(types::I32, from) @@ -146,6 +142,23 @@ pub(crate) fn clif_int_or_float_cast( fx.bcx.ins().fcvt_to_sint_sat(to_ty, from) } else { fx.bcx.ins().fcvt_to_uint_sat(to_ty, from) + }; + + if let Some(false) = fx.tcx.sess.opts.debugging_opts.saturating_float_casts { + return val; + } + + let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from); + if to_ty == types::I128 { + // FIXME(bytecodealliance/wasmtime#3963): select.i128 on fcmp eq miscompiles + let (lsb, msb) = fx.bcx.ins().isplit(val); + let zero = fx.bcx.ins().iconst(types::I64, 0); + let lsb = fx.bcx.ins().select(is_not_nan, lsb, zero); + let msb = fx.bcx.ins().select(is_not_nan, msb, zero); + fx.bcx.ins().iconcat(lsb, msb) + } else { + let zero = fx.bcx.ins().iconst(to_ty, 0); + fx.bcx.ins().select(is_not_nan, val, zero) } } else if from_ty.is_float() && to_ty.is_float() { // float -> float diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs index eef3c8c8d6e..e59a0cb0a23 100644 --- a/compiler/rustc_codegen_cranelift/src/config.rs +++ b/compiler/rustc_codegen_cranelift/src/config.rs @@ -48,12 +48,6 @@ pub struct BackendConfig { /// Can be set using `-Cllvm-args=display_cg_time=...`. pub display_cg_time: bool, - /// The register allocator to use. - /// - /// Defaults to the value of `CG_CLIF_REGALLOC` or `backtracking` otherwise. Can be set using - /// `-Cllvm-args=regalloc=...`. - pub regalloc: String, - /// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run /// once before passing the clif ir to Cranelift for compilation. /// @@ -80,8 +74,6 @@ impl Default for BackendConfig { args.split(' ').map(|arg| arg.to_string()).collect() }, display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"), - regalloc: std::env::var("CG_CLIF_REGALLOC") - .unwrap_or_else(|_| "backtracking".to_string()), enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"), disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"), } @@ -101,7 +93,6 @@ impl BackendConfig { match name { "mode" => config.codegen_mode = value.parse()?, "display_cg_time" => config.display_cg_time = parse_bool(name, value)?, - "regalloc" => config.regalloc = value.to_string(), "enable_verifier" => config.enable_verifier = parse_bool(name, value)?, "disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?, _ => return Err(format!("Unknown option `{}`", name)), diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 357cb4a6d24..f619bb5ed5e 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -128,8 +128,16 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let relative_discr = if niche_start == 0 { tag } else { - // FIXME handle niche_start > i64::MAX - fx.bcx.ins().iadd_imm(tag, -i64::try_from(niche_start).unwrap()) + let niche_start = match fx.bcx.func.dfg.value_type(tag) { + types::I128 => { + let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64); + let msb = + fx.bcx.ins().iconst(types::I64, (niche_start >> 64) as u64 as i64); + fx.bcx.ins().iconcat(lsb, msb) + } + ty => fx.bcx.ins().iconst(ty, niche_start as i64), + }; + fx.bcx.ins().isub(tag, niche_start) }; let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); let is_niche = { diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 310d27c6dec..d76dfca7960 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1019,39 +1019,23 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); }; - // In Rust floating point min and max don't propagate NaN. In Cranelift they do however. - // For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*` - // and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing - // a float against itself. Only in case of NaN is it not equal to itself. minnumf32, (v a, v b) { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); - let temp = fx.bcx.ins().select(a_ge_b, b, a); - let val = fx.bcx.ins().select(a_is_nan, b, temp); + let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); }; minnumf64, (v a, v b) { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); - let temp = fx.bcx.ins().select(a_ge_b, b, a); - let val = fx.bcx.ins().select(a_is_nan, b, temp); + let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); }; maxnumf32, (v a, v b) { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); - let temp = fx.bcx.ins().select(a_le_b, b, a); - let val = fx.bcx.ins().select(a_is_nan, b, temp); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); }; maxnumf64, (v a, v b) { - let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); - let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); - let temp = fx.bcx.ins().select(a_le_b, b, a); - let val = fx.bcx.ins().select(a_is_nan, b, temp); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); }; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index bc21d736166..d1ca9edf2e0 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -322,20 +322,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } assert_eq!(a.layout(), b.layout()); assert_eq!(a.layout(), c.layout()); - let layout = a.layout(); + assert_eq!(a.layout(), ret.layout()); - let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_count, ret_lane_count); - let ret_lane_layout = fx.layout_of(ret_lane_ty); + let layout = a.layout(); + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); for lane in 0..lane_count { - let a_lane = a.value_lane(fx, lane).load_scalar(fx); - let b_lane = b.value_lane(fx, lane).load_scalar(fx); - let c_lane = c.value_lane(fx, lane).load_scalar(fx); + let a_lane = a.value_lane(fx, lane); + let b_lane = b.value_lane(fx, lane); + let c_lane = c.value_lane(fx, lane); - let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane); - let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout); + let res_lane = match lane_ty.kind() { + ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty), + ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty), + _ => unreachable!(), + }; ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } @@ -354,8 +355,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!("{:?}", lane_ty), } match intrinsic { - sym::simd_fmin => fx.bcx.ins().fmin(x_lane, y_lane), - sym::simd_fmax => fx.bcx.ins().fmax(x_lane, y_lane), + sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane), + sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane), _ => unreachable!(), } }); @@ -495,7 +496,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let lt = match ty.kind() { ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b), ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b), - ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b), + ty::Float(_) => return crate::num::codegen_float_min(fx, a, b), _ => unreachable!(), }; fx.bcx.ins().select(lt, a, b) @@ -512,7 +513,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let gt = match ty.kind() { ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b), ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b), - ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b), + ty::Float(_) => return crate::num::codegen_float_max(fx, a, b), _ => unreachable!(), }; fx.bcx.ins().select(gt, a, b) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 878b9390e13..9d2e12f9898 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -256,8 +256,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); - flags_builder.set("regalloc", &backend_config.regalloc).unwrap(); - use rustc_session::config::OptLevel; match sess.opts.optimize { OptLevel::No => { diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index 545d390e269..4ce8adb182e 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -420,3 +420,21 @@ pub(crate) fn codegen_ptr_binop<'tcx>( CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool)) } } + +// In Rust floating point min and max don't propagate NaN. In Cranelift they do however. +// For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*` +// and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing +// a float against itself. Only in case of NaN is it not equal to itself. +pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_ge_b, b, a); + fx.bcx.ins().select(a_is_nan, b, temp) +} + +pub(crate) fn codegen_float_max(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { + let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a); + let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b); + let temp = fx.bcx.ins().select(a_le_b, b, a); + fx.bcx.ins().select(a_is_nan, b, temp) +} diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 2af050f0c75..2e8cd934eb2 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -589,6 +589,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => unimplemented!(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(), InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(), InlineAsmRegClass::X86( X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg, @@ -654,6 +655,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(), InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") @@ -784,6 +786,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option _ => unreachable!(), }, InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None, InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { unreachable!("clobber-only") } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index dff32007918..e994001f96f 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -602,7 +602,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk", InlineAsmRegClass::X86( - X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg, + X86InlineAsmRegClass::x87_reg + | X86InlineAsmRegClass::mmx_reg + | X86InlineAsmRegClass::kreg0, ) => unreachable!("clobber-only"), InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", @@ -687,7 +689,11 @@ fn modifier_to_llvm( _ => unreachable!(), }, InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, - InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { + InlineAsmRegClass::X86( + X86InlineAsmRegClass::x87_reg + | X86InlineAsmRegClass::mmx_reg + | X86InlineAsmRegClass::kreg0, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, @@ -757,7 +763,11 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), - InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { + InlineAsmRegClass::X86( + X86InlineAsmRegClass::x87_reg + | X86InlineAsmRegClass::mmx_reg + | X86InlineAsmRegClass::kreg0, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 74e194750fa..f2cf3b1ef5c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -437,11 +437,9 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - DINodeCreationResult::new(build_basic_type_di_node(cx, t), false) - } - ty::Tuple(elements) if elements.is_empty() => { - DINodeCreationResult::new(build_basic_type_di_node(cx, t), false) + build_basic_type_di_node(cx, t) } + ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t), ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t), ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id), ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id), @@ -640,7 +638,10 @@ impl MsvcBasicName for ty::FloatTy { } } -fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn build_basic_type_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, +) -> DINodeCreationResult<'ll> { debug!("build_basic_type_di_node: {:?}", t); // When targeting MSVC, emit MSVC style type names for compatibility with @@ -649,7 +650,13 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), - ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned), + ty::Tuple(elements) if elements.is_empty() => { + if cpp_like_debuginfo { + return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t)); + } else { + ("()", DW_ATE_unsigned) + } + } ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_UTF), ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed), @@ -672,14 +679,14 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - }; if !cpp_like_debuginfo { - return ty_di_node; + return DINodeCreationResult::new(ty_di_node, false); } let typedef_name = match t.kind() { ty::Int(int_ty) => int_ty.name_str(), ty::Uint(uint_ty) => uint_ty.name_str(), ty::Float(float_ty) => float_ty.name_str(), - _ => return ty_di_node, + _ => return DINodeCreationResult::new(ty_di_node, false), }; let typedef_di_node = unsafe { @@ -694,7 +701,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) - ) }; - typedef_di_node + DINodeCreationResult::new(typedef_di_node, false) } fn build_foreign_type_di_node<'ll, 'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index cf32d558d4a..4d20ed841d4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -987,7 +987,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( // On MSVC packed debug information is produced by the linker itself so // there's no need to do anything else here. - SplitDebuginfo::Packed if sess.target.is_like_msvc => {} + SplitDebuginfo::Packed if sess.target.is_like_windows => {} // ... and otherwise we're processing a `*.dwp` packed dwarf file. // diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 765bd877db1..7b7c676c26c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,12 +1,10 @@ use std::collections::hash_map::Entry::*; use rustc_ast::expand::allocator::ALLOCATOR_METHODS; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::Node; -use rustc_index::vec::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportLevel, @@ -277,17 +275,6 @@ fn upstream_monomorphizations_provider( let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default(); - let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = { - let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, cnums.len() + 1); - - for &cnum in cnums.iter() { - cnum_stable_ids[cnum] = - tcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).0; - } - - cnum_stable_ids - }; - let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn(); for &cnum in cnums.iter() { @@ -316,7 +303,7 @@ fn upstream_monomorphizations_provider( // If there are multiple monomorphizations available, // we select one deterministically. let other_cnum = *e.get(); - if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] { + if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) { e.insert(cnum); } } diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 80270f82563..68f9bee593f 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -38,7 +38,7 @@ pub(crate) fn const_caller_location( if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() { bug!("intern_const_alloc_recursive should not error in this case") } - ConstValue::Scalar(Scalar::from_pointer(loc_place.ptr.into_pointer_or_addr().unwrap(), &tcx)) + ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx)) } /// Convert an evaluated constant to a type level constant diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index f0fff602fe4..827959113b9 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -679,7 +679,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_place: Option<&PlaceTy<'tcx, M::PointerTag>>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { - debug!("body: {:#?}", body); + trace!("body: {:#?}", body); // first push a stack frame so we have access to the local substs let pre_frame = Frame { body, @@ -836,7 +836,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()); } - debug!("locals: {:#?}", frame.locals); + trace!("locals: {:#?}", frame.locals); // Cleanup: deallocate all locals that are backed by an allocation. for local in &frame.locals { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index ddfbcbdd22e..7721485771b 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -88,6 +88,10 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to. type PointerTag: Provenance + Eq + Hash + 'static; + /// When getting the AllocId of a pointer, some extra data is also obtained from the tag + /// that is passed to memory access hooks so they can do things with it. + type TagExtra: Copy + 'static; + /// Machines can define extra (non-instance) things that represent values of function pointers. /// For example, Miri uses this to return a function pointer from `dlsym` /// that can later be called to execute the right thing. @@ -122,6 +126,8 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether, when checking alignment, we should `force_int` and thus support /// custom alignment logic based on whatever the integer address happens to be. + /// + /// Requires PointerTag::OFFSET_IS_ADDR to be true. fn force_int_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether to enforce the validity invariant @@ -285,11 +291,14 @@ pub trait Machine<'mir, 'tcx>: Sized { addr: u64, ) -> Pointer<Option<Self::PointerTag>>; - /// Convert a pointer with provenance into an allocation-offset pair. + /// Convert a pointer with provenance into an allocation-offset pair + /// and extra provenance info. + /// + /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`. fn ptr_get_alloc( ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer<Self::PointerTag>, - ) -> (AllocId, Size); + ) -> (AllocId, Size, Self::TagExtra); /// Called to initialize the "extra" state of an allocation and make the pointers /// it contains (in relocations) tagged. The way we construct allocations is @@ -321,7 +330,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &Self, _alloc_extra: &Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -333,7 +342,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -345,7 +354,7 @@ pub trait Machine<'mir, 'tcx>: Sized { _tcx: TyCtxt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, - _tag: Self::PointerTag, + _tag: (AllocId, Self::TagExtra), _range: AllocRange, ) -> InterpResult<'tcx> { Ok(()) @@ -397,6 +406,8 @@ pub trait Machine<'mir, 'tcx>: Sized { // (CTFE and ConstProp) use the same instance. Here, we share that code. pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type PointerTag = AllocId; + type TagExtra = (); + type ExtraFnVal = !; type MemoryMap = @@ -474,9 +485,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) { + fn ptr_get_alloc( + _ecx: &InterpCx<$mir, $tcx, Self>, + ptr: Pointer<AllocId>, + ) -> (AllocId, Size, Self::TagExtra) { // We know `offset` is relative to the allocation, so we can use `into_parts`. let (alloc_id, offset) = ptr.into_parts(); - (alloc_id, offset) + (alloc_id, offset, ()) } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a165fa23f30..b1d7ab6a098 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -158,8 +158,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, ptr: Pointer<AllocId>, ) -> InterpResult<'tcx, Pointer<M::PointerTag>> { - // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (alloc_id, offset) = ptr.into_parts(); + let alloc_id = ptr.provenance; // We need to handle `extern static`. match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => { @@ -171,7 +170,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => {} } // And we need to get the tag. - Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset))) + Ok(M::tag_alloc_base_pointer(self, ptr)) } pub fn create_fn_alloc_ptr( @@ -238,7 +237,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { new_align: Align, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx, Pointer<M::PointerTag>> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub_format!( "reallocating {:?} which does not point to the beginning of an object", @@ -255,14 +254,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // This will also call the access hooks. self.mem_copy( - ptr.into(), + ptr, Align::ONE, new_ptr.into(), Align::ONE, old_size.min(new_size), /*nonoverlapping*/ true, )?; - self.deallocate_ptr(ptr.into(), old_size_and_align, kind)?; + self.deallocate_ptr(ptr, old_size_and_align, kind)?; Ok(new_ptr) } @@ -274,7 +273,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { old_size_and_align: Option<(Size, Align)>, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?; trace!("deallocating: {}", alloc_id); if offset.bytes() != 0 { @@ -330,7 +329,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { *self.tcx, &mut self.machine, &mut alloc.extra, - ptr.provenance, + (alloc_id, tag), alloc_range(Size::ZERO, size), )?; @@ -350,17 +349,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer<Option<M::PointerTag>>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>> { + ) -> InterpResult<'tcx, Option<(AllocId, Size, M::TagExtra)>> { let align = M::enforce_alignment(&self).then_some(align); self.check_and_deref_ptr( ptr, size, align, CheckInAllocMsg::MemoryAccessTest, - |alloc_id, offset, ptr| { + |alloc_id, offset, tag| { let (size, align) = self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; - Ok((size, align, (alloc_id, offset, ptr))) + Ok((size, align, (alloc_id, offset, tag))) }, ) } @@ -401,11 +400,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { size: Size, align: Option<Align>, msg: CheckInAllocMsg, - alloc_size: impl FnOnce( - AllocId, - Size, - Pointer<M::PointerTag>, - ) -> InterpResult<'tcx, (Size, Align, T)>, + alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>, ) -> InterpResult<'tcx, Option<T>> { fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { if offset % align.bytes() == 0 { @@ -433,8 +428,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } None } - Ok((alloc_id, offset, ptr)) => { - let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, ptr)?; + Ok((alloc_id, offset, tag)) => { + let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, tag)?; // Test bounds. This also ensures non-null. // It is sufficient to check this for the end pointer. Also check for overflow! if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) { @@ -450,10 +445,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // we want the error to be about the bounds. if let Some(align) = align { if M::force_int_for_alignment_check(self) { - let addr = Scalar::from_pointer(ptr, &self.tcx) - .to_machine_usize(&self.tcx) - .expect("ptr-to-int cast for align check should never fail"); - check_offset_align(addr, align)?; + // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. + check_offset_align(ptr.addr().bytes(), align)?; } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { @@ -569,14 +562,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { size, align, CheckInAllocMsg::MemoryAccessTest, - |alloc_id, offset, ptr| { + |alloc_id, offset, tag| { let alloc = self.get_alloc_raw(alloc_id)?; - Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc))) + Ok((alloc.size(), alloc.align, (alloc_id, offset, tag, alloc))) }, )?; - if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc { + if let Some((alloc_id, offset, tag, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - M::memory_read(*self.tcx, &self.machine, &alloc.extra, ptr.provenance, range)?; + M::memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, tag), range)?; Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in @@ -631,13 +624,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { align: Align, ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>> { let parts = self.get_ptr_access(ptr, size, align)?; - if let Some((alloc_id, offset, ptr)) = parts { + if let Some((alloc_id, offset, tag)) = parts { let tcx = *self.tcx; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::memory_written(tcx, machine, &mut alloc.extra, ptr.provenance, range)?; + M::memory_written(tcx, machine, &mut alloc.extra, (alloc_id, tag), range)?; Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) } else { Ok(None) @@ -732,7 +725,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer<Option<M::PointerTag>>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { trace!("get_fn({:?})", ptr); - let (alloc_id, offset, _ptr) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } @@ -877,9 +870,17 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { range: AllocRange, val: ScalarMaybeUninit<Tag>, ) -> InterpResult<'tcx> { + let range = self.range.subrange(range); + debug!( + "write_scalar in {} at {:#x}, size {}: {:?}", + self.alloc_id, + range.start.bytes(), + range.size.bytes(), + val + ); Ok(self .alloc - .write_scalar(&self.tcx, self.range.subrange(range), val) + .write_scalar(&self.tcx, range, val) .map_err(|e| e.to_interp_error(self.alloc_id))?) } @@ -892,17 +893,29 @@ impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> { } /// Mark the entire referenced range as uninitalized - pub fn write_uninit(&mut self) { - self.alloc.mark_init(self.range, false); + pub fn write_uninit(&mut self) -> InterpResult<'tcx> { + Ok(self + .alloc + .write_uninit(&self.tcx, self.range) + .map_err(|e| e.to_interp_error(self.alloc_id))?) } } impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> { pub fn read_scalar(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { - Ok(self + let range = self.range.subrange(range); + let res = self .alloc - .read_scalar(&self.tcx, self.range.subrange(range)) - .map_err(|e| e.to_interp_error(self.alloc_id))?) + .read_scalar(&self.tcx, range) + .map_err(|e| e.to_interp_error(self.alloc_id))?; + debug!( + "read_scalar in {} at {:#x}, size {}: {:?}", + self.alloc_id, + range.start.bytes(), + range.size.bytes(), + res + ); + Ok(res) } pub fn read_ptr_sized(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { @@ -1009,16 +1022,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // and once below to get the underlying `&[mut] Allocation`. // Source alloc preparations and access hooks. - let Some((src_alloc_id, src_offset, src)) = src_parts else { + let Some((src_alloc_id, src_offset, src_tag)) = src_parts else { // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. return Ok(()); }; let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - M::memory_read(*tcx, &self.machine, &src_alloc.extra, src.provenance, src_range)?; + M::memory_read(*tcx, &self.machine, &src_alloc.extra, (src_alloc_id, src_tag), src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. - let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else { + let Some((dest_alloc_id, dest_offset, dest_tag)) = dest_parts else { // Zero-sized *destination*. return Ok(()); }; @@ -1040,7 +1053,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Destination alloc preparations and access hooks. let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); - M::memory_written(*tcx, extra, &mut dest_alloc.extra, dest.provenance, dest_range)?; + M::memory_written( + *tcx, + extra, + &mut dest_alloc.extra, + (dest_alloc_id, dest_tag), + dest_range, + )?; let dest_bytes = dest_alloc .get_bytes_mut_ptr(&tcx, dest_range) .map_err(|e| e.to_interp_error(dest_alloc_id))? @@ -1053,8 +1072,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This also avoids writing to the target bytes so that the backing allocation is never // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary // operating system this can avoid physically allocating the page. - dest_alloc.mark_init(dest_range, false); // `Size` multiplication - dest_alloc.mark_relocation_range(relocations); + dest_alloc + .write_uninit(&tcx, dest_range) + .map_err(|e| e.to_interp_error(dest_alloc_id))?; + // We can forget about the relocations, this is all not initialized anyway. return Ok(()); } @@ -1159,11 +1180,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn ptr_try_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, - ) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64> { + ) -> Result<(AllocId, Size, M::TagExtra), u64> { match ptr.into_pointer_or_addr() { Ok(ptr) => { - let (alloc_id, offset) = M::ptr_get_alloc(self, ptr); - Ok((alloc_id, offset, ptr)) + let (alloc_id, offset, extra) = M::ptr_get_alloc(self, ptr); + Ok((alloc_id, offset, extra)) } Err(addr) => Err(addr.bytes()), } @@ -1174,7 +1195,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn ptr_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, - ) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)> { + ) -> InterpResult<'tcx, (AllocId, Size, M::TagExtra)> { self.ptr_try_get_alloc_id(ptr).map_err(|offset| { err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into() }) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 31da4522a1f..e4660fe090c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -823,7 +823,7 @@ where // Zero-sized access return Ok(()); }; - alloc.write_uninit(); + alloc.write_uninit()?; Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 4a0aa41de73..71d29be97d5 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -432,7 +432,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' if let Some(ref mut ref_tracking) = self.ref_tracking { // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { + if let Ok((alloc_id, _offset, _tag)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { // Special handling for pointers to statics (irrespective of their type). let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 79d427ccc44..f71bc586b48 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -214,7 +214,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed. - if self.tcx.sess.opts.debugging_opts.validate_mir { + if self.tcx.sess.opts.debugging_opts.validate_mir && self.mir_phase < MirPhase::DropsLowered + { // `Operand::Copy` is only supposed to be used with `Copy` types. if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 85ad0f2f7f5..25353290fd5 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -207,9 +207,14 @@ pub trait ToStableHashKey<HCX> { fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; } -// Implement HashStable by just calling `Hash::hash()`. This works fine for -// self-contained values that don't depend on the hashing context `CTX`. -#[macro_export] +/// Implement HashStable by just calling `Hash::hash()`. +/// +/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting. +/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013) +/// for examples). Therefore this macro is not exported and should only be used in the limited cases +/// here in this module. +/// +/// Use `#[derive(HashStable_Generic)]` instead. macro_rules! impl_stable_hash_via_hash { ($t:ty) => { impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t { @@ -246,12 +251,14 @@ impl<CTX> HashStable<CTX> for ! { } impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 { + #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) } } impl<CTX> HashStable<CTX> for ::std::num::NonZeroUsize { + #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) } @@ -272,12 +279,14 @@ impl<CTX> HashStable<CTX> for f64 { } impl<CTX> HashStable<CTX> for ::std::cmp::Ordering { + #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { (*self as i8).hash_stable(ctx, hasher); } } impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) { + #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { let (ref _0,) = *self; _0.hash_stable(ctx, hasher); diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index de0dd18cc6e..e1e0ed7222d 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -338,18 +338,12 @@ impl MultiSpan { /// Returns `true` if any of the primary spans are displayable. pub fn has_primary_spans(&self) -> bool { - self.primary_spans.iter().any(|sp| !sp.is_dummy()) + !self.is_dummy() } /// Returns `true` if this contains only a dummy primary span with any hygienic context. pub fn is_dummy(&self) -> bool { - let mut is_dummy = true; - for span in &self.primary_spans { - if !span.is_dummy() { - is_dummy = false; - } - } - is_dummy + self.primary_spans.iter().all(|sp| sp.is_dummy()) } /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9cd072c8b4c..cd17726c785 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,12 +1,11 @@ use crate::snippet::Style; use crate::{ CodeSuggestion, DiagnosticMessage, Level, MultiSpan, Substitution, SubstitutionPart, - SuggestionStyle, ToolMetadata, + SuggestionStyle, }; use rustc_data_structures::stable_map::FxHashMap; use rustc_error_messages::FluentValue; use rustc_lint_defs::{Applicability, LintExpectationId}; -use rustc_serialize::json::Json; use rustc_span::edition::LATEST_STABLE_EDITION; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -554,7 +553,6 @@ impl Diagnostic { msg: msg.into(), style, applicability, - tool_metadata: Default::default(), }); self } @@ -582,7 +580,6 @@ impl Diagnostic { msg: msg.into(), style: SuggestionStyle::CompletelyHidden, applicability, - tool_metadata: Default::default(), }); self } @@ -637,7 +634,6 @@ impl Diagnostic { msg: msg.into(), style, applicability, - tool_metadata: Default::default(), }); self } @@ -680,7 +676,6 @@ impl Diagnostic { msg: msg.into(), style: SuggestionStyle::ShowCode, applicability, - tool_metadata: Default::default(), }); self } @@ -705,7 +700,6 @@ impl Diagnostic { msg: msg.into(), style: SuggestionStyle::ShowCode, applicability, - tool_metadata: Default::default(), }); self } @@ -774,23 +768,6 @@ impl Diagnostic { self } - /// Adds a suggestion intended only for a tool. The intent is that the metadata encodes - /// the suggestion in a tool-specific way, as it may not even directly involve Rust code. - pub fn tool_only_suggestion_with_metadata( - &mut self, - msg: impl Into<DiagnosticMessage>, - applicability: Applicability, - tool_metadata: Json, - ) { - self.push_suggestion(CodeSuggestion { - substitutions: vec![], - msg: msg.into(), - style: SuggestionStyle::CompletelyHidden, - applicability, - tool_metadata: ToolMetadata::new(tool_metadata), - }) - } - pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 0139007da42..d680e7fab70 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -14,7 +14,6 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use crate::emitter::{Emitter, HumanReadableErrorType}; use crate::registry::Registry; use crate::DiagnosticId; -use crate::ToolMetadata; use crate::{ CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic, }; @@ -30,7 +29,6 @@ use std::sync::{Arc, Mutex}; use std::vec; use rustc_serialize::json::{as_json, as_pretty_json}; -use rustc_serialize::{Encodable, Encoder}; #[cfg(test)] mod tests; @@ -205,8 +203,7 @@ impl Emitter for JsonEmitter { // The following data types are provided just for serialisation. -// NOTE: this has a manual implementation of Encodable which needs to be updated in -// parallel. +#[derive(Encodable)] struct Diagnostic { /// The primary error message. message: String, @@ -218,65 +215,6 @@ struct Diagnostic { children: Vec<Diagnostic>, /// The message as rustc would render it. rendered: Option<String>, - /// Extra tool metadata - tool_metadata: ToolMetadata, -} - -macro_rules! encode_fields { - ( - $enc:expr, // encoder - $idx:expr, // starting field index - $struct:expr, // struct we're serializing - $struct_name:ident, // struct name - [ $($name:ident),+$(,)? ], // fields to encode - [ $($ignore:ident),+$(,)? ] // fields we're skipping - ) => { - { - // Pattern match to make sure all fields are accounted for - let $struct_name { $($name,)+ $($ignore: _,)+ } = $struct; - let mut idx = $idx; - $( - $enc.emit_struct_field( - stringify!($name), - idx == 0, - |enc| $name.encode(enc), - )?; - idx += 1; - )+ - idx - } - }; -} - -// Special-case encoder to skip tool_metadata if not set -impl<E: Encoder> Encodable<E> for Diagnostic { - fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_struct(false, |s| { - let mut idx = 0; - - idx = encode_fields!( - s, - idx, - self, - Self, - [message, code, level, spans, children, rendered], - [tool_metadata] - ); - if self.tool_metadata.is_set() { - idx = encode_fields!( - s, - idx, - self, - Self, - [tool_metadata], - [message, code, level, spans, children, rendered] - ); - } - - let _ = idx; - Ok(()) - }) - } } #[derive(Encodable)] @@ -380,7 +318,6 @@ impl Diagnostic { spans: DiagnosticSpan::from_suggestion(sugg, &args, je), children: vec![], rendered: None, - tool_metadata: sugg.tool_metadata.clone(), } }); @@ -428,7 +365,6 @@ impl Diagnostic { .chain(sugg) .collect(), rendered: Some(output), - tool_metadata: ToolMetadata::default(), } } @@ -449,7 +385,6 @@ impl Diagnostic { .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)), children: vec![], rendered: None, - tool_metadata: ToolMetadata::default(), } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index d7c5df7d8e2..4e6ab0edf66 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -36,13 +36,12 @@ pub use rustc_error_messages::{ LazyFallbackBundle, MultiSpan, SpanLabel, DEFAULT_LOCALE_RESOURCES, }; pub use rustc_lint_defs::{pluralize, Applicability}; -use rustc_serialize::json::Json; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::source_map::SourceMap; +use rustc_span::HashStableContext; use rustc_span::{Loc, Span}; use std::borrow::Cow; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::num::NonZeroUsize; use std::panic; use std::path::Path; @@ -93,39 +92,6 @@ impl SuggestionStyle { } } -#[derive(Clone, Debug, PartialEq, Default)] -pub struct ToolMetadata(pub Option<Json>); - -impl ToolMetadata { - fn new(json: Json) -> Self { - ToolMetadata(Some(json)) - } - - fn is_set(&self) -> bool { - self.0.is_some() - } -} - -impl Hash for ToolMetadata { - fn hash<H: Hasher>(&self, _state: &mut H) {} -} - -// Doesn't really need to round-trip -impl<D: Decoder> Decodable<D> for ToolMetadata { - fn decode(_d: &mut D) -> Self { - ToolMetadata(None) - } -} - -impl<S: Encoder> Encodable<S> for ToolMetadata { - fn encode(&self, e: &mut S) -> Result<(), S::Error> { - match &self.0 { - None => e.emit_unit(), - Some(json) => json.encode(e), - } - } -} - #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct CodeSuggestion { /// Each substitute can have multiple variants due to multiple @@ -159,8 +125,6 @@ pub struct CodeSuggestion { /// which are useful for users but not useful for /// tools like rustfix pub applicability: Applicability, - /// Tool-specific metadata - pub tool_metadata: ToolMetadata, } #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] @@ -1531,6 +1495,7 @@ pub fn add_elided_lifetime_in_path_suggestion( /// Useful type to use with `Result<>` indicate that an error has already /// been reported to the user, so no need to continue checking. #[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(HashStable_Generic)] pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { @@ -1540,5 +1505,3 @@ impl ErrorGuaranteed { ErrorGuaranteed(()) } } - -rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index aec401a041c..8e1966a0711 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -9,6 +9,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorGuaranteed; use rustc_parse::nt_to_tokenstream; use rustc_parse::parser::ForceCollect; +use rustc_span::profiling::SpannedEventArgRecorder; use rustc_span::{Span, DUMMY_SP}; const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; @@ -25,7 +26,10 @@ impl base::ProcMacro for BangProcMacro { input: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { let _timer = - ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); + ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { + recorder.record_arg_with_span(ecx.expansion_descr(), span); + }); + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| { @@ -51,7 +55,10 @@ impl base::AttrProcMacro for AttrProcMacro { annotated: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { let _timer = - ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); + ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { + recorder.record_arg_with_span(ecx.expansion_descr(), span); + }); + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); self.client @@ -103,7 +110,9 @@ impl MultiItemModifier for ProcMacroDerive { let stream = { let _timer = - ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); + ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { + recorder.record_arg_with_span(ecx.expansion_descr(), span); + }); let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) { diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 53d60d280c0..324e1100057 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -1,4 +1,4 @@ -use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::def_id::DefId; use crate::hir; use rustc_ast as ast; @@ -124,9 +124,7 @@ impl DefKind { pub fn descr(self, def_id: DefId) -> &'static str { match self { DefKind::Fn => "function", - DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => { - "crate" - } + DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate", DefKind::Mod => "module", DefKind::Static(..) => "static", DefKind::Enum => "enum", diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 4908992085a..bce9ba12ac0 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -353,11 +353,6 @@ impl Definitions { } } - /// Retrieves the root definition. - pub fn get_root_def(&self) -> LocalDefId { - LocalDefId { local_def_index: CRATE_DEF_INDEX } - } - /// Adds a definition with a parent definition. pub fn create_def( &mut self, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b3de86662eb..ef56093bed8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4,8 +4,8 @@ crate use crate::hir_id::{HirId, ItemLocalId}; use crate::intravisit::FnKind; use crate::LangItem; +use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; -use rustc_ast::{self as ast, CrateSugar}; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{CaptureBy, Movability, Mutability}; @@ -2140,10 +2140,10 @@ impl ImplItemId { pub struct ImplItem<'hir> { pub ident: Ident, pub def_id: LocalDefId, - pub vis: Visibility<'hir>, pub generics: Generics<'hir>, pub kind: ImplItemKind<'hir>, pub span: Span, + pub vis_span: Span, } impl ImplItem<'_> { @@ -2645,34 +2645,11 @@ pub struct PolyTraitRef<'hir> { pub span: Span, } -pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>; - -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum VisibilityKind<'hir> { - Public, - Crate(CrateSugar), - Restricted { path: &'hir Path<'hir>, hir_id: HirId }, - Inherited, -} - -impl VisibilityKind<'_> { - pub fn is_pub(&self) -> bool { - matches!(*self, VisibilityKind::Public) - } - - pub fn is_pub_restricted(&self) -> bool { - match *self { - VisibilityKind::Public | VisibilityKind::Inherited => false, - VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true, - } - } -} - #[derive(Debug, HashStable_Generic)] pub struct FieldDef<'hir> { pub span: Span, + pub vis_span: Span, pub ident: Ident, - pub vis: Visibility<'hir>, pub hir_id: HirId, pub ty: &'hir Ty<'hir>, } @@ -2744,8 +2721,8 @@ pub struct Item<'hir> { pub ident: Ident, pub def_id: LocalDefId, pub kind: ItemKind<'hir>, - pub vis: Visibility<'hir>, pub span: Span, + pub vis_span: Span, } impl Item<'_> { @@ -3002,7 +2979,7 @@ pub struct ForeignItem<'hir> { pub kind: ForeignItemKind<'hir>, pub def_id: LocalDefId, pub span: Span, - pub vis: Visibility<'hir>, + pub vis_span: Span, } impl ForeignItem<'_> { @@ -3210,7 +3187,6 @@ pub enum Node<'hir> { Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam<'hir>), - Visibility(&'hir Visibility<'hir>), Crate(&'hir Mod<'hir>), @@ -3253,7 +3229,6 @@ impl<'hir> Node<'hir> { | Node::Binding(..) | Node::Arm(..) | Node::Local(..) - | Node::Visibility(..) | Node::Crate(..) | Node::Ty(..) | Node::TraitRef(..) @@ -3318,18 +3293,18 @@ impl<'hir> Node<'hir> { match self { Node::Item(i) => match i.kind { ItemKind::Fn(ref sig, ref generics, _) => { - Some(FnKind::ItemFn(i.ident, generics, sig.header, &i.vis)) + Some(FnKind::ItemFn(i.ident, generics, sig.header)) } _ => None, }, Node::TraitItem(ti) => match ti.kind { TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => { - Some(FnKind::Method(ti.ident, sig, None)) + Some(FnKind::Method(ti.ident, sig)) } _ => None, }, Node::ImplItem(ii) => match ii.kind { - ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig, Some(&ii.vis))), + ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)), _ => None, }, Node::Expr(e) => match e.kind { @@ -3350,8 +3325,8 @@ mod size_asserts { rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); - rustc_data_structures::static_assert_size!(super::Item<'static>, 184); + rustc_data_structures::static_assert_size!(super::Item<'static>, 160); rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128); - rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 144); - rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 136); + rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 120); + rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 112); } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 3b5e4dcf5e0..346ac9e9644 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,4 +1,4 @@ -use crate::def_id::{LocalDefId, CRATE_DEF_INDEX}; +use crate::def_id::{LocalDefId, CRATE_DEF_ID}; use std::fmt; /// Uniquely identifies a node in the HIR of the current crate. It is @@ -76,16 +76,14 @@ rustc_index::newtype_index! { /// integers starting at zero, so a mapping that maps all or most nodes within /// an "item-like" to something else can be implemented by a `Vec` instead of a /// tree or hash map. + #[derive(HashStable_Generic)] pub struct ItemLocalId { .. } } -rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); + impl ItemLocalId { /// Signal local id which should never be used. pub const INVALID: ItemLocalId = ItemLocalId::MAX; } -/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. -pub const CRATE_HIR_ID: HirId = HirId { - owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, - local_id: ItemLocalId::from_u32(0), -}; +/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. +pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) }; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8689e2c2afa..59bd46ae353 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -100,10 +100,10 @@ where #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` - ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>), + ItemFn(Ident, &'a Generics<'a>, FnHeader), /// `fn foo(&self)` - Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>), + Method(Ident, &'a FnSig<'a>), /// `|x, y| {}` Closure, @@ -112,8 +112,8 @@ pub enum FnKind<'a> { impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&FnHeader> { match *self { - FnKind::ItemFn(_, _, ref header, _) => Some(header), - FnKind::Method(_, ref sig, _) => Some(&sig.header), + FnKind::ItemFn(_, _, ref header) => Some(header), + FnKind::Method(_, ref sig) => Some(&sig.header), FnKind::Closure => None, } } @@ -475,9 +475,6 @@ pub trait Visitor<'v>: Sized { walk_assoc_type_binding(self, type_binding) } fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {} - fn visit_vis(&mut self, vis: &'v Visibility<'v>) { - walk_vis(self, vis) - } fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) { walk_associated_item_kind(self, kind); } @@ -554,7 +551,6 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) { } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { - visitor.visit_vis(&item.vis); visitor.visit_ident(item.ident); match item.kind { ItemKind::ExternCrate(orig_name) => { @@ -572,7 +568,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { visitor.visit_nested_body(body); } ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn( - FnKind::ItemFn(item.ident, generics, sig.header, &item.vis), + FnKind::ItemFn(item.ident, generics, sig.header), &sig.decl, body_id, item.span, @@ -859,7 +855,6 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) { visitor.visit_id(foreign_item.hir_id()); - visitor.visit_vis(&foreign_item.vis); visitor.visit_ident(foreign_item.ident); match foreign_item.kind { @@ -999,7 +994,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { visitor.visit_fn( - FnKind::Method(trait_item.ident, sig, None), + FnKind::Method(trait_item.ident, sig), &sig.decl, body_id, trait_item.span, @@ -1025,10 +1020,9 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItem { def_id: _, ident, ref vis, ref generics, ref kind, span: _ } = *impl_item; + let ImplItem { def_id: _, ident, ref generics, ref kind, span: _, vis_span: _ } = *impl_item; visitor.visit_ident(ident); - visitor.visit_vis(vis); visitor.visit_generics(generics); match *kind { ImplItemKind::Const(ref ty, body) => { @@ -1038,7 +1032,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt } ImplItemKind::Fn(ref sig, body_id) => { visitor.visit_fn( - FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)), + FnKind::Method(impl_item.ident, sig), &sig.decl, body_id, impl_item.span, @@ -1082,7 +1076,6 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>( pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) { visitor.visit_id(field.hir_id); - visitor.visit_vis(&field.vis); visitor.visit_ident(field.ident); visitor.visit_ty(&field.ty); } @@ -1250,13 +1243,6 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { visitor.visit_expr(&arm.body); } -pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) { - if let VisibilityKind::Restricted { ref path, hir_id } = vis.node { - visitor.visit_id(hir_id); - visitor.visit_path(path, hir_id) - } -} - pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) { // No visitable content here: this fn exists so you can call it if // the right thing to do, should content be added in the future, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 27f07a479b1..87ff9457783 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -8,12 +8,11 @@ use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir as hir; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; -use rustc_span::source_map::{SourceMap, Spanned}; +use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; use rustc_span::{self, FileName}; use rustc_target::spec::abi::Abi; -use std::borrow::Cow; use std::cell::Cell; use std::vec; @@ -98,7 +97,6 @@ impl<'a> State<'a> { self.print_block(&a) } Node::Lifetime(a) => self.print_lifetime(&a), - Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => panic!("cannot print Node::GenericParam"), Node::Field(_) => panic!("cannot print Node::Field"), // These cases do not carry enough information in the @@ -191,13 +189,6 @@ where printer.s.eof() } -pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_>, w: S) -> String { - to_string(NO_ANN, |s| { - s.print_visibility(vis); - s.word(w) - }) -} - pub fn generic_params_to_string(generic_params: &[GenericParam<'_>]) -> String { to_string(NO_ANN, |s| s.print_generic_params(generic_params)) } @@ -223,11 +214,10 @@ pub fn fn_to_string( header: hir::FnHeader, name: Option<Symbol>, generics: &hir::Generics<'_>, - vis: &hir::Visibility<'_>, arg_names: &[Ident], body_id: Option<hir::BodyId>, ) -> String { - to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, vis, arg_names, body_id)) + to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, arg_names, body_id)) } pub fn enum_def_to_string( @@ -235,9 +225,8 @@ pub fn enum_def_to_string( generics: &hir::Generics<'_>, name: Symbol, span: rustc_span::Span, - visibility: &hir::Visibility<'_>, ) -> String { - to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span, visibility)) + to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span)) } impl<'a> State<'a> { @@ -395,7 +384,6 @@ impl<'a> State<'a> { }, Some(item.ident.name), generics, - &item.vis, arg_names, None, ); @@ -404,7 +392,7 @@ impl<'a> State<'a> { self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { - self.head(visibility_qualified(&item.vis, "static")); + self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } @@ -416,7 +404,7 @@ impl<'a> State<'a> { self.end() // end the outer cbox } hir::ForeignItemKind::Type => { - self.head(visibility_qualified(&item.vis, "type")); + self.head("type"); self.print_ident(item.ident); self.word(";"); self.end(); // end the head-ibox @@ -430,9 +418,8 @@ impl<'a> State<'a> { ident: Ident, ty: &hir::Ty<'_>, default: Option<hir::BodyId>, - vis: &hir::Visibility<'_>, ) { - self.word(visibility_qualified(vis, "")); + self.head(""); self.word_space("const"); self.print_ident(ident); self.word_space(":"); @@ -473,7 +460,7 @@ impl<'a> State<'a> { generics: &hir::Generics<'_>, inner: impl Fn(&mut Self), ) { - self.head(visibility_qualified(&item.vis, "type")); + self.head("type"); self.print_ident(item.ident); self.print_generic_params(&generics.params); self.end(); // end the inner ibox @@ -494,7 +481,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Item(item)); match item.kind { hir::ItemKind::ExternCrate(orig_name) => { - self.head(visibility_qualified(&item.vis, "extern crate")); + self.head("extern crate"); if let Some(orig_name) = orig_name { self.print_name(orig_name); self.space(); @@ -507,7 +494,7 @@ impl<'a> State<'a> { self.end(); // end outer head-block } hir::ItemKind::Use(ref path, kind) => { - self.head(visibility_qualified(&item.vis, "use")); + self.head("use"); self.print_path(path, false); match kind { @@ -526,7 +513,7 @@ impl<'a> State<'a> { self.end(); // end outer head-block } hir::ItemKind::Static(ref ty, m, expr) => { - self.head(visibility_qualified(&item.vis, "static")); + self.head("static"); if m == hir::Mutability::Mut { self.word_space("mut"); } @@ -542,7 +529,7 @@ impl<'a> State<'a> { self.end(); // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { - self.head(visibility_qualified(&item.vis, "const")); + self.head("const"); self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); @@ -561,7 +548,6 @@ impl<'a> State<'a> { sig.header, Some(item.ident.name), param_names, - &item.vis, &[], Some(body), ); @@ -571,12 +557,10 @@ impl<'a> State<'a> { self.ann.nested(self, Nested::Body(body)); } hir::ItemKind::Macro(ref macro_def, _) => { - self.print_mac_def(macro_def, &item.ident, item.span, |state| { - state.print_visibility(&item.vis) - }); + self.print_mac_def(macro_def, &item.ident, item.span, |_| {}); } hir::ItemKind::Mod(ref _mod) => { - self.head(visibility_qualified(&item.vis, "mod")); + self.head("mod"); self.print_ident(item.ident); self.nbsp(); self.bopen(); @@ -594,7 +578,7 @@ impl<'a> State<'a> { self.bclose(item.span); } hir::ItemKind::GlobalAsm(ref asm) => { - self.head(visibility_qualified(&item.vis, "global_asm!")); + self.head("global_asm!"); self.print_inline_asm(asm); self.end() } @@ -620,14 +604,14 @@ impl<'a> State<'a> { }); } hir::ItemKind::Enum(ref enum_definition, ref params) => { - self.print_enum_def(enum_definition, params, item.ident.name, item.span, &item.vis); + self.print_enum_def(enum_definition, params, item.ident.name, item.span); } hir::ItemKind::Struct(ref struct_def, ref generics) => { - self.head(visibility_qualified(&item.vis, "struct")); + self.head("struct"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } hir::ItemKind::Union(ref struct_def, ref generics) => { - self.head(visibility_qualified(&item.vis, "union")); + self.head("union"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } hir::ItemKind::Impl(hir::Impl { @@ -642,7 +626,6 @@ impl<'a> State<'a> { items, }) => { self.head(""); - self.print_visibility(&item.vis); self.print_defaultness(defaultness); self.print_unsafety(unsafety); self.word_nbsp("impl"); @@ -679,7 +662,6 @@ impl<'a> State<'a> { } hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => { self.head(""); - self.print_visibility(&item.vis); self.print_is_auto(is_auto); self.print_unsafety(unsafety); self.word_nbsp("trait"); @@ -705,7 +687,7 @@ impl<'a> State<'a> { self.bclose(item.span); } hir::ItemKind::TraitAlias(ref generics, ref bounds) => { - self.head(visibility_qualified(&item.vis, "trait")); + self.head("trait"); self.print_ident(item.ident); self.print_generic_params(&generics.params); let mut real_bounds = Vec::with_capacity(bounds.len()); @@ -753,9 +735,8 @@ impl<'a> State<'a> { generics: &hir::Generics<'_>, name: Symbol, span: rustc_span::Span, - visibility: &hir::Visibility<'_>, ) { - self.head(visibility_qualified(visibility, "enum")); + self.head("enum"); self.print_name(name); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); @@ -778,27 +759,6 @@ impl<'a> State<'a> { self.bclose(span) } - pub fn print_visibility(&mut self, vis: &hir::Visibility<'_>) { - match vis.node { - hir::VisibilityKind::Public => self.word_nbsp("pub"), - hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"), - hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"), - hir::VisibilityKind::Restricted { ref path, .. } => { - self.word("pub("); - if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super { - // Special case: `super` can print like `pub(super)`. - self.word("super"); - } else { - // Everything else requires `in` at present. - self.word_nbsp("in"); - self.print_path(path, false); - } - self.word_nbsp(")"); - } - hir::VisibilityKind::Inherited => (), - } - } - pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) { match defaultness { hir::Defaultness::Default { .. } => self.word_nbsp("default"), @@ -823,7 +783,6 @@ impl<'a> State<'a> { self.commasep(Inconsistent, struct_def.fields(), |s, field| { s.maybe_print_comment(field.span.lo()); s.print_outer_attributes(s.attrs(field.hir_id)); - s.print_visibility(&field.vis); s.print_type(&field.ty) }); self.pclose(); @@ -845,7 +804,6 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(field.span.lo()); self.print_outer_attributes(self.attrs(field.hir_id)); - self.print_visibility(&field.vis); self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(&field.ty); @@ -872,11 +830,10 @@ impl<'a> State<'a> { ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, - vis: &hir::Visibility<'_>, arg_names: &[Ident], body_id: Option<hir::BodyId>, ) { - self.print_fn(&m.decl, m.header, Some(ident.name), generics, vis, arg_names, body_id) + self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id) } pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -886,21 +843,15 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(ti.hir_id())); match ti.kind { hir::TraitItemKind::Const(ref ty, default) => { - let vis = - Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; - self.print_associated_const(ti.ident, &ty, default, &vis); + self.print_associated_const(ti.ident, &ty, default); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => { - let vis = - Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; - self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); + self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - let vis = - Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.head(""); - self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body)); + self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box @@ -926,11 +877,11 @@ impl<'a> State<'a> { match ii.kind { hir::ImplItemKind::Const(ref ty, expr) => { - self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis); + self.print_associated_const(ii.ident, &ty, Some(expr)); } hir::ImplItemKind::Fn(ref sig, body) => { self.head(""); - self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body)); + self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body)); self.nbsp(); self.end(); // need to close a box self.end(); // need to close a box @@ -2008,11 +1959,10 @@ impl<'a> State<'a> { header: hir::FnHeader, name: Option<Symbol>, generics: &hir::Generics<'_>, - vis: &hir::Visibility<'_>, arg_names: &[Ident], body_id: Option<hir::BodyId>, ) { - self.print_fn_header_info(header, vis); + self.print_fn_header_info(header); if let Some(name) = name { self.nbsp(); @@ -2301,16 +2251,13 @@ impl<'a> State<'a> { }, name, &generics, - &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }, arg_names, None, ); self.end(); } - pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { - self.word(visibility_qualified(vis, "")); - + pub fn print_fn_header_info(&mut self, header: hir::FnHeader) { match header.constness { hir::Constness::NotConst => {} hir::Constness::Const => self.word_nbsp("const"), diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 60b48e9bc8a..2d06c9d8ec9 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -241,7 +241,7 @@ fn dump_graph(query: &DepGraphQuery) { let targets = node_set(&query, &edge_filter.target); filter_nodes(&query, &sources, &targets) } - Err(_) => query.nodes().into_iter().collect(), + Err(_) => query.nodes().into_iter().map(|n| n.kind).collect(), }; let edges = filter_edges(&query, &nodes); @@ -264,33 +264,33 @@ fn dump_graph(query: &DepGraphQuery) { } #[allow(missing_docs)] -pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>); +pub struct GraphvizDepGraph(FxHashSet<DepKind>, Vec<(DepKind, DepKind)>); -impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); - fn nodes(&self) -> dot::Nodes<'_, &'q DepNode> { +impl<'a> dot::GraphWalk<'a> for GraphvizDepGraph { + type Node = DepKind; + type Edge = (DepKind, DepKind); + fn nodes(&self) -> dot::Nodes<'_, DepKind> { let nodes: Vec<_> = self.0.iter().cloned().collect(); nodes.into() } - fn edges(&self) -> dot::Edges<'_, (&'q DepNode, &'q DepNode)> { + fn edges(&self) -> dot::Edges<'_, (DepKind, DepKind)> { self.1[..].into() } - fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn source(&self, edge: &(DepKind, DepKind)) -> DepKind { edge.0 } - fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn target(&self, edge: &(DepKind, DepKind)) -> DepKind { edge.1 } } -impl<'a, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); +impl<'a> dot::Labeller<'a> for GraphvizDepGraph { + type Node = DepKind; + type Edge = (DepKind, DepKind); fn graph_id(&self) -> dot::Id<'_> { dot::Id::new("DependencyGraph").unwrap() } - fn node_id(&self, n: &&'q DepNode) -> dot::Id<'_> { + fn node_id(&self, n: &DepKind) -> dot::Id<'_> { let s: String = format!("{:?}", n) .chars() .map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' }) @@ -298,7 +298,7 @@ impl<'a, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { debug!("n={:?} s={:?}", n, s); dot::Id::new(s).unwrap() } - fn node_label(&self, n: &&'q DepNode) -> dot::LabelText<'_> { + fn node_label(&self, n: &DepKind) -> dot::LabelText<'_> { dot::LabelText::label(format!("{:?}", n)) } } @@ -323,7 +323,7 @@ fn filter_nodes<'q>( query: &'q DepGraphQuery, sources: &Option<FxHashSet<&'q DepNode>>, targets: &Option<FxHashSet<&'q DepNode>>, -) -> FxHashSet<&'q DepNode> { +) -> FxHashSet<DepKind> { if let Some(sources) = sources { if let Some(targets) = targets { walk_between(query, sources, targets) @@ -333,7 +333,7 @@ fn filter_nodes<'q>( } else if let Some(targets) = targets { walk_nodes(query, targets, INCOMING) } else { - query.nodes().into_iter().collect() + query.nodes().into_iter().map(|n| n.kind).collect() } } @@ -341,17 +341,17 @@ fn walk_nodes<'q>( query: &'q DepGraphQuery, starts: &FxHashSet<&'q DepNode>, direction: Direction, -) -> FxHashSet<&'q DepNode> { +) -> FxHashSet<DepKind> { let mut set = FxHashSet::default(); for &start in starts { debug!("walk_nodes: start={:?} outgoing?={:?}", start, direction == OUTGOING); - if set.insert(start) { + if set.insert(start.kind) { let mut stack = vec![query.indices[start]]; while let Some(index) = stack.pop() { for (_, edge) in query.graph.adjacent_edges(index, direction) { let neighbor_index = edge.source_or_target(direction); let neighbor = query.graph.node_data(neighbor_index); - if set.insert(neighbor) { + if set.insert(neighbor.kind) { stack.push(neighbor_index); } } @@ -365,7 +365,7 @@ fn walk_between<'q>( query: &'q DepGraphQuery, sources: &FxHashSet<&'q DepNode>, targets: &FxHashSet<&'q DepNode>, -) -> FxHashSet<&'q DepNode> { +) -> FxHashSet<DepKind> { // This is a bit tricky. We want to include a node only if it is: // (a) reachable from a source and (b) will reach a target. And we // have to be careful about cycles etc. Luckily efficiency is not @@ -396,6 +396,7 @@ fn walk_between<'q>( let index = query.indices[n]; node_states[index.0] == State::Included }) + .map(|n| n.kind) .collect(); fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) -> bool { @@ -433,11 +434,13 @@ fn walk_between<'q>( fn filter_edges<'q>( query: &'q DepGraphQuery, - nodes: &FxHashSet<&'q DepNode>, -) -> Vec<(&'q DepNode, &'q DepNode)> { - query + nodes: &FxHashSet<DepKind>, +) -> Vec<(DepKind, DepKind)> { + let uniq: FxHashSet<_> = query .edges() .into_iter() - .filter(|&(source, target)| nodes.contains(source) && nodes.contains(target)) - .collect() + .map(|(s, t)| (s.kind, t.kind)) + .filter(|(source, target)| nodes.contains(source) && nodes.contains(target)) + .collect(); + uniq.into_iter().collect() } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 86229dbfad7..0ca0fe33614 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -567,11 +567,17 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles // (e.g., #41849). - relate::relate_substs(self, None, a_subst, b_subst) + relate::relate_substs(self, a_subst, b_subst) } else { let tcx = self.tcx(); let opt_variances = tcx.variances_of(item_def_id); - relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst) + relate::relate_substs_with_variances( + self, + item_def_id, + &opt_variances, + a_subst, + b_subst, + ) } } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 65c0eba4b3d..ef6d464d3c6 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -53,7 +53,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { // performing trait matching (which then performs equality // unification). - relate::relate_substs(self, None, a_subst, b_subst) + relate::relate_substs(self, a_subst, b_subst) } fn relate_with_variance<T: Relate<'tcx>>( diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f2dd4f5d5cb..f9273cc50b7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -61,7 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::dep_graph::DepContext; @@ -2285,7 +2285,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) { - self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit(); + let owner = + self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner); + self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit(); } pub fn construct_generic_bound_failure( @@ -2294,31 +2296,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: Option<SubregionOrigin<'tcx>>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, + owner: Option<LocalDefId>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let hir = self.tcx.hir(); // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. - let generics = self - .in_progress_typeck_results - .map(|typeck_results| typeck_results.borrow().hir_owner) - .map(|owner| { - let hir_id = hir.local_def_id_to_hir_id(owner); - let parent_id = hir.get_parent_item(hir_id); - ( - // Parent item could be a `mod`, so we check the HIR before calling: - if let Some(Node::Item(Item { - kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, - .. - })) = hir.find_by_def_id(parent_id) - { - Some(self.tcx.generics_of(parent_id)) - } else { - None - }, - self.tcx.generics_of(owner.to_def_id()), - hir.span(hir_id), - ) - }); + let generics = owner.map(|owner| { + let hir_id = hir.local_def_id_to_hir_id(owner); + let parent_id = hir.get_parent_item(hir_id); + ( + // Parent item could be a `mod`, so we check the HIR before calling: + if let Some(Node::Item(Item { + kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, + .. + })) = hir.find_by_def_id(parent_id) + { + Some(self.tcx.generics_of(parent_id)) + } else { + None + }, + self.tcx.generics_of(owner.to_def_id()), + hir.span(hir_id), + ) + }); let span = match generics { // This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal @@ -2606,11 +2606,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None, ); if let Some(infer::RelateParamBound(_, t, _)) = origin { - let return_impl_trait = self - .in_progress_typeck_results - .map(|typeck_results| typeck_results.borrow().hir_owner) - .and_then(|owner| self.tcx.return_type_impl_trait(owner)) - .is_some(); + let return_impl_trait = + owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some(); let t = self.resolve_vars_if_possible(t); match t.kind() { // We've got: diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index fe75ee8b37b..1327bf6fcd4 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -66,6 +66,7 @@ where location: ExternLocation::ExactPaths(locations), is_private_dep: false, add_prelude: true, + nounused_dep: false, } } @@ -751,6 +752,7 @@ fn test_debugging_options_tracking_hash() { tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); + tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, Some(true)); diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 8ea47dda928..02f747eeccc 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -18,7 +18,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_feature = { path = "../rustc_feature" } rustc_index = { path = "../rustc_index" } rustc_session = { path = "../rustc_session" } -rustc_serialize = { path = "../rustc_serialize" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 77fe76af2de..68658e2616e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -36,8 +36,7 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; -use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind}; -use rustc_hir::{HirId, Node}; +use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind}; use rustc_index::vec::Idx; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; @@ -487,9 +486,6 @@ declare_lint! { pub struct MissingDoc { /// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes. doc_hidden_stack: Vec<bool>, - - /// Private traits or trait items that leaked through. Don't check their methods. - private_traits: FxHashSet<hir::HirId>, } impl_lint_pass!(MissingDoc => [MISSING_DOCS]); @@ -520,7 +516,7 @@ fn has_doc(attr: &ast::Attribute) -> bool { impl MissingDoc { pub fn new() -> MissingDoc { - MissingDoc { doc_hidden_stack: vec![false], private_traits: FxHashSet::default() } + MissingDoc { doc_hidden_stack: vec![false] } } fn doc_hidden(&self) -> bool { @@ -598,30 +594,16 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { match it.kind { - hir::ItemKind::Trait(.., trait_item_refs) => { + hir::ItemKind::Trait(..) => { // Issue #11592: traits are always considered exported, even when private. - if let hir::VisibilityKind::Inherited = it.vis.node { - self.private_traits.insert(it.hir_id()); - for trait_item_ref in trait_item_refs { - self.private_traits.insert(trait_item_ref.id.hir_id()); - } + if cx.tcx.visibility(it.def_id) + == ty::Visibility::Restricted( + cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(), + ) + { return; } } - hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), items, .. }) => { - // If the trait is private, add the impl items to `private_traits` so they don't get - // reported for missing docs. - let real_trait = trait_ref.path.res.def_id(); - let Some(def_id) = real_trait.as_local() else { return }; - let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(def_id) else { return }; - if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in items { - self.private_traits.insert(impl_item_ref.id.hir_id()); - } - } - return; - } - hir::ItemKind::TyAlias(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Macro(..) @@ -641,10 +623,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { - if self.private_traits.contains(&trait_item.hir_id()) { - return; - } - let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); self.check_missing_docs_attrs(cx, trait_item.def_id, trait_item.span, article, desc); @@ -1384,46 +1362,47 @@ impl UnreachablePub { cx: &LateContext<'_>, what: &str, def_id: LocalDefId, - vis: &hir::Visibility<'_>, span: Span, + vis_span: Span, exportable: bool, ) { let mut applicability = Applicability::MachineApplicable; - match vis.node { - hir::VisibilityKind::Public if !cx.access_levels.is_reachable(def_id) => { - if span.from_expansion() { - applicability = Applicability::MaybeIncorrect; + if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) { + if vis_span.from_expansion() { + applicability = Applicability::MaybeIncorrect; + } + let def_span = cx.tcx.sess.source_map().guess_head_span(span); + cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { + let mut err = lint.build(&format!("unreachable `pub` {}", what)); + let replacement = if cx.tcx.features().crate_visibility_modifier { + "crate" + } else { + "pub(crate)" } - let def_span = cx.tcx.sess.source_map().guess_head_span(span); - cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { - let mut err = lint.build(&format!("unreachable `pub` {}", what)); - let replacement = if cx.tcx.features().crate_visibility_modifier { - "crate" - } else { - "pub(crate)" - } - .to_owned(); + .to_owned(); - err.span_suggestion( - vis.span, - "consider restricting its visibility", - replacement, - applicability, - ); - if exportable { - err.help("or consider exporting it for use by other crates"); - } - err.emit(); - }); - } - _ => {} + err.span_suggestion( + vis_span, + "consider restricting its visibility", + replacement, + applicability, + ); + if exportable { + err.help("or consider exporting it for use by other crates"); + } + err.emit(); + }); } } } impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - self.perform_lint(cx, "item", item.def_id, &item.vis, item.span, true); + // Do not warn for fake `use` statements. + if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { + return; + } + self.perform_lint(cx, "item", item.def_id, item.span, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { @@ -1431,19 +1410,29 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { cx, "item", foreign_item.def_id, - &foreign_item.vis, foreign_item.span, + foreign_item.vis_span, true, ); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { let def_id = cx.tcx.hir().local_def_id(field.hir_id); - self.perform_lint(cx, "field", def_id, &field.vis, field.span, false); + self.perform_lint(cx, "field", def_id, field.span, field.vis_span, false); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { - self.perform_lint(cx, "item", impl_item.def_id, &impl_item.vis, impl_item.span, false); + // Only lint inherent impl items. + if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { + self.perform_lint( + cx, + "item", + impl_item.def_id, + impl_item.span, + impl_item.vis_span, + false, + ); + } } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 152c53dac7f..0ffa65b79b5 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -33,8 +33,7 @@ use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt}; -use rustc_serialize::json::Json; -use rustc_session::lint::{BuiltinLintDiagnostics, ExternDepSpec}; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; use rustc_span::lev_distance::find_best_match_for_name; @@ -728,30 +727,6 @@ pub trait LintContext: Sized { BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => { db.span_label(span, "the attribute is introduced here"); } - BuiltinLintDiagnostics::ExternDepSpec(krate, loc) => { - let json = match loc { - ExternDepSpec::Json(json) => { - db.help(&format!("remove unnecessary dependency `{}`", krate)); - json - } - ExternDepSpec::Raw(raw) => { - db.help(&format!("remove unnecessary dependency `{}` at `{}`", krate, raw)); - db.span_suggestion_with_style( - DUMMY_SP, - "raw extern location", - raw.clone(), - Applicability::Unspecified, - SuggestionStyle::CompletelyHidden, - ); - Json::String(raw) - } - }; - db.tool_only_suggestion_with_metadata( - "json extern location", - Applicability::Unspecified, - json - ); - } BuiltinLintDiagnostics::ProcMacroBackCompat(note) => { db.note(¬e); } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index f73388c675e..e1507d0fbb4 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -406,7 +406,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } _ => (), }, - FnKind::ItemFn(ident, _, header, _) => { + FnKind::ItemFn(ident, _, header) => { // Skip foreign-ABI #[no_mangle] functions (Issue #31924) if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) { return; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4debbf26be6..f590172af4f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,8 +8,8 @@ use rustc_ast::node_id::{NodeId, NodeMap}; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_error_messages::MultiSpan; +use rustc_hir::HashStableContext; use rustc_hir::HirId; -use rustc_serialize::json::Json; use rustc_span::edition::Edition; use rustc_span::{sym, symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; @@ -147,7 +147,7 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation /// Setting for how to handle a lint. /// /// See: <https://doc.rust-lang.org/rustc/lints/levels.html> -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)] pub enum Level { /// The `allow` level will not issue any message. Allow, @@ -175,8 +175,6 @@ pub enum Level { Forbid, } -rustc_data_structures::impl_stable_hash_via_hash!(Level); - impl Level { /// Converts a level to a lower-case string. pub fn as_str(self) -> &'static str { @@ -403,13 +401,6 @@ impl<HCX> ToStableHashKey<HCX> for LintId { } } -// Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency -#[derive(PartialEq, Debug)] -pub enum ExternDepSpec { - Json(Json), - Raw(String), -} - // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] @@ -428,7 +419,6 @@ pub enum BuiltinLintDiagnostics { UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span }, PatternsInFnsWithoutBody(Span, Ident), LegacyDeriveHelpers(Span), - ExternDepSpec(String, ExternDepSpec), ProcMacroBackCompat(String), OrPatternsBackCompat(Span, String), ReservedPrefix(Span), diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index 46f698f6f9b..ff7506979fc 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -16,20 +16,27 @@ use std::collections::{BTreeSet, HashMap}; /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(SessionDiagnostic)] -/// #[error(code = "E0505", slug = "move-out-of-borrow-error")] +/// #[error(code = "E0505", slug = "borrowck-move-out-of-borrow")] /// pub struct MoveOutOfBorrowError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, /// #[primary_span] -/// #[label = "cannot move out of borrow"] +/// #[label] /// pub span: Span, -/// #[label = "`{ty}` first borrowed here"] -/// pub other_span: Span, -/// #[suggestion(message = "consider cloning here", code = "{name}.clone()")] -/// pub opt_sugg: Option<(Span, Applicability)> +/// #[label = "first-borrow-label"] +/// pub first_borrow_span: Span, +/// #[suggestion(code = "{name}.clone()")] +/// pub clone_sugg: Option<(Span, Applicability)> /// } /// ``` /// +/// ```fluent +/// move-out-of-borrow = cannot move out of {$name} because it is borrowed +/// .label = cannot move out of borrow +/// .first-borrow-label = `{$ty}` first borrowed here +/// .suggestion = consider cloning here +/// ``` +/// /// Then, later, to emit the error: /// /// ```ignore (pseudo-rust) @@ -37,10 +44,13 @@ use std::collections::{BTreeSet, HashMap}; /// expected, /// actual, /// span, -/// other_span, -/// opt_sugg: Some(suggestion, Applicability::MachineApplicable), +/// first_borrow_span, +/// clone_sugg: Some(suggestion, Applicability::MachineApplicable), /// }); /// ``` +/// +/// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`: +/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html> pub fn session_diagnostic_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { // Names for the diagnostic we build and the session we build it from. let diag = format_ident!("diag"); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 566d27212d0..e8cdae7fd25 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -13,11 +13,10 @@ use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; use rustc_middle::ty::TyCtxt; -use rustc_serialize::json::ToJson; use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate}; use rustc_session::cstore::{ExternCrateSource, MetadataLoaderDyn}; -use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec}; +use rustc_session::lint; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_session::Session; @@ -27,7 +26,6 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use proc_macro::bridge::client::ProcMacro; -use std::collections::BTreeMap; use std::ops::Fn; use std::path::Path; use std::{cmp, env}; @@ -909,6 +907,10 @@ impl<'a> CrateLoader<'a> { // Don't worry about pathless `--extern foo` sysroot references continue; } + if entry.nounused_dep { + // We're not worried about this one + continue; + } let name_interned = Symbol::intern(name); if self.used_extern_options.contains(&name_interned) { continue; @@ -920,20 +922,7 @@ impl<'a> CrateLoader<'a> { continue; } - let diag = match self.sess.opts.extern_dep_specs.get(name) { - Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()), - None => { - // If we don't have a specific location, provide a json encoding of the `--extern` - // option. - let meta: BTreeMap<String, String> = - std::iter::once(("name".to_string(), name.to_string())).collect(); - BuiltinLintDiagnostics::ExternDepSpec( - name.clone(), - ExternDepSpec::Json(meta.to_json()), - ) - } - }; - self.sess.parse_sess.buffer_lint_with_diagnostic( + self.sess.parse_sess.buffer_lint( lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, @@ -942,7 +931,6 @@ impl<'a> CrateLoader<'a> { name, self.local_crate_name, name), - diag, ); } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 611694a0d30..77afa7b4a5c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -28,6 +28,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::GeneratorDiagnosticData; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::cstore::{ @@ -1725,6 +1726,28 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .collect() }) } + + fn get_generator_diagnostic_data( + self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> Option<GeneratorDiagnosticData<'tcx>> { + self.root + .tables + .generator_diagnostic_data + .get(self, id) + .map(|param| param.decode((self, tcx))) + .map(|generator_data| GeneratorDiagnosticData { + generator_interior_types: generator_data.generator_interior_types, + hir_owner: generator_data.hir_owner, + nodes_types: generator_data.nodes_types, + adjustments: generator_data.adjustments, + }) + } + + fn get_may_have_doc_links(self, index: DefIndex) -> bool { + self.root.tables.may_have_doc_links.get(self, index).is_some() + } } impl CrateMetadata { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 63bf929fb86..1156a78e8a9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -5,7 +5,7 @@ use crate::native_libs; use rustc_ast as ast; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::exported_symbols::ExportedSymbol; @@ -246,6 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, crate_extern_paths => { cdata.source().paths().cloned().collect() } expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } + generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) } } pub(in crate::rmeta) fn provide(providers: &mut Providers) { @@ -324,7 +325,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { continue; } - bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX }); + bfs_queue.push_back(cnum.as_def_id()); } let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &ModChild, parent: DefId| { @@ -530,6 +531,18 @@ impl CStore { ) -> impl Iterator<Item = DefId> + '_ { self.get_crate_data(cnum).get_all_incoherent_impls() } + + pub fn associated_item_def_ids_untracked<'a>( + &'a self, + def_id: DefId, + sess: &'a Session, + ) -> impl Iterator<Item = DefId> + 'a { + self.get_crate_data(def_id.krate).get_associated_item_def_ids(def_id.index, sess) + } + + pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool { + self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index) + } } impl CrateStore for CStore { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6a8d4e03754..f485e09913e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -977,6 +977,14 @@ fn should_encode_generics(def_kind: DefKind) -> bool { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn encode_attrs(&mut self, def_id: DefId) { + let attrs = self.tcx.get_attrs(def_id); + record!(self.tables.attributes[def_id] <- attrs); + if attrs.iter().any(|attr| attr.may_have_doc_links()) { + self.tables.may_have_doc_links.set(def_id.index, ()); + } + } + fn encode_def_ids(&mut self) { if self.is_proc_macro { return; @@ -989,7 +997,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let Some(def_kind) = def_kind else { continue }; self.tables.opt_def_kind.set(def_id.index, def_kind); record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); - record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id)); + self.encode_attrs(def_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); if should_encode_visibility(def_kind) { record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id)); @@ -1556,16 +1564,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_closure(&mut self, hir_id: hir::HirId) { let def_id = self.tcx.hir().local_def_id(hir_id); debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic, // including on the signature, which is inferred in `typeck. - let ty = self.tcx.typeck(def_id).node_type(hir_id); - + let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id); + let ty = typeck_result.node_type(hir_id); match ty.kind() { ty::Generator(..) => { let data = self.tcx.generator_kind(def_id).unwrap(); + let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data(); record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator); record!(self.tables.generator_kind[def_id.to_def_id()] <- data); + record!(self.tables.generator_diagnostic_data[def_id.to_def_id()] <- generator_diagnostic_data); } ty::Closure(..) => { @@ -1639,7 +1648,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let hir = tcx.hir(); let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index; - let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)); + let stability = tcx.lookup_stability(CRATE_DEF_ID); let macros = self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); @@ -1650,7 +1659,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod); record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); - record!(self.tables.attributes[LOCAL_CRATE.as_def_id()] <- tcx.get_attrs(LOCAL_CRATE.as_def_id())); + self.encode_attrs(LOCAL_CRATE.as_def_id()); record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id())); if let Some(stability) = stability { record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability); @@ -1691,7 +1700,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = id.to_def_id(); self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind)); record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind)); - record!(self.tables.attributes[def_id] <- attrs); + self.encode_attrs(def_id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); record!(self.tables.def_span[def_id] <- span); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 43ccfc64e05..f1498665ff3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,6 +19,7 @@ use rustc_middle::mir; use rustc_middle::thir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; +use rustc_middle::ty::GeneratorDiagnosticData; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; @@ -358,6 +359,8 @@ define_tables! { def_keys: Table<DefIndex, Lazy<DefKey>>, def_path_hashes: Table<DefIndex, DefPathHash>, proc_macro_quoted_spans: Table<usize, Lazy<Span>>, + generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>, + may_have_doc_links: Table<DefIndex, ()>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 7a23cba536a..53fc2efe00b 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -186,6 +186,20 @@ impl FixedSizeEncoding for Option<RawDefId> { } } +impl FixedSizeEncoding for Option<()> { + type ByteArray = [u8; 1]; + + #[inline] + fn from_bytes(b: &[u8; 1]) -> Self { + (b[0] != 0).then(|| ()) + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8; 1]) { + b[0] = self.is_some() as u8 + } +} + // NOTE(eddyb) there could be an impl for `usize`, which would enable a more // generic `Lazy<T>` impl, but in the general case we might not need / want to // fit every `usize` in `u32`. diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index d20be0a34d2..8402ca3028c 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; use rustc_query_system::dep_graph::FingerprintStyle; @@ -366,7 +366,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum { #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX }; + let def_id = self.as_def_id(); def_id.to_fingerprint(tcx) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index d74759e31a2..e0ed4022839 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -14,7 +14,6 @@ use rustc_hir::*; use rustc_index::vec::Idx; use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; -use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -304,7 +303,6 @@ impl<'hir> Map<'hir> { | Node::Param(_) | Node::Arm(_) | Node::Lifetime(_) - | Node::Visibility(_) | Node::Block(_) => return None, }; Some(def_kind) @@ -1000,12 +998,7 @@ impl<'hir> Map<'hir> { }, Node::Lifetime(lifetime) => lifetime.span, Node::GenericParam(param) => param.span, - Node::Visibility(&Spanned { - node: VisibilityKind::Restricted { ref path, .. }, - .. - }) => path.span, Node::Infer(i) => i.span, - Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, Node::Crate(item) => item.spans.inner_span, }; @@ -1128,6 +1121,10 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { } tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + // Hash visibility information since it does not appear in HIR. + let resolutions = tcx.resolutions(()); + resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); + resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) @@ -1232,7 +1229,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str), Some(Node::Lifetime(_)) => node_str("lifetime"), Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), - Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), Some(Node::Crate(..)) => String::from("root_crate"), None => format!("unknown node{}", id_str), } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fd6e241346d..758658c3d8c 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -11,7 +11,7 @@ use rustc_errors::{Applicability, Diagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self, HirId}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; @@ -370,8 +370,7 @@ impl<'tcx> TyCtxt<'tcx> { }; } - let is_staged_api = - self.lookup_stability(DefId { index: CRATE_DEF_INDEX, ..def_id }).is_some(); + let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some(); if !is_staged_api { return EvalResult::Allow; } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 438f356f072..c628406064f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -269,7 +269,7 @@ impl<Tag: Provenance, Extra> Allocation<Tag, Extra> { /// `get_bytes_with_uninit_and_ptr` instead, /// /// This function also guarantees that the resulting pointer will remain stable - /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies + /// even when new allocations are pushed to the `HashMap`. `mem_copy_repeatedly` relies /// on that. /// /// It is the caller's responsibility to check bounds and alignment beforehand. @@ -429,8 +429,7 @@ impl<Tag: Provenance, Extra> Allocation<Tag, Extra> { let val = match val { ScalarMaybeUninit::Scalar(scalar) => scalar, ScalarMaybeUninit::Uninit => { - self.mark_init(range, false); - return Ok(()); + return self.write_uninit(cx, range); } }; @@ -455,6 +454,13 @@ impl<Tag: Provenance, Extra> Allocation<Tag, Extra> { Ok(()) } + + /// Write "uninit" to the given memory range. + pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + self.mark_init(range, false); + self.clear_relocations(cx, range)?; + return Ok(()); + } } /// Relocations. @@ -509,6 +515,9 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { if Tag::ERR_ON_PARTIAL_PTR_OVERWRITE { return Err(AllocError::PartialPointerOverwrite(first)); } + warn!( + "Partial pointer overwrite! De-initializing memory at offsets {first:?}..{start:?}." + ); self.init_mask.set_range(first, start, false); } if last > end { @@ -517,10 +526,15 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { last - cx.data_layout().pointer_size, )); } + warn!( + "Partial pointer overwrite! De-initializing memory at offsets {end:?}..{last:?}." + ); self.init_mask.set_range(end, last, false); } // Forget all the relocations. + // Since relocations do not overlap, we know that removing until `last` (exclusive) is fine, + // i.e., this will not remove any other relocations just after the ones we care about. self.relocations.0.remove_range(first..last); Ok(()) @@ -561,8 +575,10 @@ impl<Tag> Deref for Relocations<Tag> { } /// A partial, owned list of relocations to transfer into another allocation. +/// +/// Offsets are already adjusted to the destination allocation. pub struct AllocationRelocations<Tag> { - relative_relocations: Vec<(Size, Tag)>, + dest_relocations: Vec<(Size, Tag)>, } impl<Tag: Copy, Extra> Allocation<Tag, Extra> { @@ -575,12 +591,17 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { ) -> AllocationRelocations<Tag> { let relocations = self.get_relocations(cx, src); if relocations.is_empty() { - return AllocationRelocations { relative_relocations: Vec::new() }; + return AllocationRelocations { dest_relocations: Vec::new() }; } let size = src.size; let mut new_relocations = Vec::with_capacity(relocations.len() * (count as usize)); + // If `count` is large, this is rather wasteful -- we are allocating a big array here, which + // is mostly filled with redundant information since it's just N copies of the same `Tag`s + // at slightly adjusted offsets. The reason we do this is so that in `mark_relocation_range` + // we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces + // the right sequence of relocations for all N copies. for i in 0..count { new_relocations.extend(relocations.iter().map(|&(offset, reloc)| { // compute offset for current repetition @@ -593,14 +614,17 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { })); } - AllocationRelocations { relative_relocations: new_relocations } + AllocationRelocations { dest_relocations: new_relocations } } /// Applies a relocation copy. /// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected /// to be clear of relocations. + /// + /// This is dangerous to use as it can violate internal `Allocation` invariants! + /// It only exists to support an efficient implementation of `mem_copy_repeatedly`. pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>) { - self.relocations.0.insert_presorted(relocations.relative_relocations); + self.relocations.0.insert_presorted(relocations.dest_relocations); } } @@ -1056,7 +1080,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { }) } - pub fn mark_init(&mut self, range: AllocRange, is_init: bool) { + fn mark_init(&mut self, range: AllocRange, is_init: bool) { if range.size.bytes() == 0 { return; } @@ -1118,6 +1142,9 @@ impl<Tag, Extra> Allocation<Tag, Extra> { } /// Applies multiple instances of the run-length encoding to the initialization mask. + /// + /// This is dangerous to use as it can violate internal `Allocation` invariants! + /// It only exists to support an efficient implementation of `mem_copy_repeatedly`. pub fn mark_compressed_init_range( &mut self, defined: &InitMaskCompressed, diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 813c0912f53..c71aea417ec 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -163,6 +163,9 @@ pub struct Pointer<Tag = AllocId> { } static_assert_size!(Pointer, 16); +// `Option<Tag>` pointers are also passed around quite a bit +// (but not stored in permanent machine state). +static_assert_size!(Pointer<Option<AllocId>>, 16); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. @@ -198,12 +201,26 @@ impl<Tag> From<Pointer<Tag>> for Pointer<Option<Tag>> { } impl<Tag> Pointer<Option<Tag>> { + /// Convert this pointer that *might* have a tag into a pointer that *definitely* has a tag, or + /// an absolute address. + /// + /// This is rarely what you want; call `ptr_try_get_alloc_id` instead. pub fn into_pointer_or_addr(self) -> Result<Pointer<Tag>, Size> { match self.provenance { Some(tag) => Ok(Pointer::new(tag, self.offset)), None => Err(self.offset), } } + + /// Returns the absolute address the pointer points to. + /// Only works if Tag::OFFSET_IS_ADDR is true! + pub fn addr(self) -> Size + where + Tag: Provenance, + { + assert!(Tag::OFFSET_IS_ADDR); + self.offset + } } impl<Tag> Pointer<Option<Tag>> { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 49769b7ae3d..881f59ae464 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -15,7 +15,7 @@ use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex} use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{CtorKind, Namespace}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::{self, GeneratorKind}; use rustc_hir::{self as hir, HirId}; use rustc_session::Session; @@ -166,7 +166,8 @@ pub enum MirPhase { /// * [`StatementKind::Retag`] /// /// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop` - /// terminator means that the auto-generated drop glue will be invoked. + /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands + /// are allowed for non-`Copy` types. DropsLowered = 3, /// Beginning with this phase, the following variant is disallowed: /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` @@ -385,7 +386,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { let mut body = Body { phase: MirPhase::Built, - source: MirSource::item(DefId::local(CRATE_DEF_INDEX)), + source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks, source_scopes: IndexVec::new(), generator: None, @@ -2330,7 +2331,10 @@ pub struct SourceScopeLocalData { /// validator. #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum Operand<'tcx> { - /// Creates a value by loading the given place. The type of the place must be `Copy` + /// Creates a value by loading the given place. + /// + /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there + /// is no such requirement. Copy(Place<'tcx>), /// Creates a value by performing loading the place, just like the `Copy` operand. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 69dac038839..b7f695da544 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -851,6 +851,7 @@ fn write_allocation_bytes<'tcx, Tag: Provenance, Extra>( } if let Some(&tag) = alloc.relocations().get(&i) { // Memory with a relocation must be defined + assert!(alloc.init_mask().is_range_initialized(i, i + ptr_size).is_ok()); let j = i.bytes_usize(); let offset = alloc .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 999cb9f30b8..78a33832433 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1969,4 +1969,10 @@ rustc_queries! { eval_always desc { "computing the backend features for CLI flags" } } + + query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> { + storage(ArenaCacheSelector<'tcx>) + desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) } + separate_provide_extern + } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index e56efb8d497..fdf5ecfdaf7 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -66,7 +66,7 @@ macro_rules! thir_with_elements { /// A container for a THIR body. /// /// This can be indexed directly by any THIR index (e.g. [`ExprId`]). - #[derive(Debug, HashStable)] + #[derive(Debug, HashStable, Clone)] pub struct Thir<'tcx> { $( pub $name: IndexVec<$id, $value>, @@ -106,7 +106,7 @@ pub enum LintLevel { Explicit(hir::HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Block { /// Whether the block itself has a label. Used by `label: {}` /// and `try` blocks. @@ -125,7 +125,7 @@ pub struct Block { pub safety_mode: BlockSafety, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Adt<'tcx> { /// The ADT we're constructing. pub adt_def: AdtDef<'tcx>, @@ -151,13 +151,13 @@ pub enum BlockSafety { ExplicitUnsafe(hir::HirId), } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Stmt<'tcx> { pub kind: StmtKind<'tcx>, pub opt_destruction_scope: Option<region::Scope>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum StmtKind<'tcx> { /// An expression with a trailing semicolon. Expr { @@ -196,7 +196,7 @@ pub enum StmtKind<'tcx> { rustc_data_structures::static_assert_size!(Expr<'_>, 104); /// A THIR expression. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { /// The type of this expression pub ty: Ty<'tcx>, @@ -212,7 +212,7 @@ pub struct Expr<'tcx> { pub kind: ExprKind<'tcx>, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum ExprKind<'tcx> { /// `Scope`s are used to explicitly mark destruction scopes, /// and to track the `HirId` of the expressions within the scope. @@ -461,20 +461,20 @@ impl<'tcx> ExprKind<'tcx> { /// Represents the association of a field identifier and an expression. /// /// This is used in struct constructors. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FieldExpr { pub name: Field, pub expr: ExprId, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct FruInfo<'tcx> { pub base: ExprId, pub field_types: Box<[Ty<'tcx>]>, } /// A `match` arm. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub struct Arm<'tcx> { pub pattern: Pat<'tcx>, pub guard: Option<Guard<'tcx>>, @@ -485,7 +485,7 @@ pub struct Arm<'tcx> { } /// A `match` guard. -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum Guard<'tcx> { If(ExprId), IfLet(Pat<'tcx>, ExprId), @@ -499,7 +499,7 @@ pub enum LogicalOp { Or, } -#[derive(Debug, HashStable)] +#[derive(Clone, Debug, HashStable)] pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 4b7c1d44cea..7af7eb4f5ec 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -44,10 +44,12 @@ pub struct ConstS<'tcx> { static_assert_size!(ConstS<'_>, 48); impl<'tcx> Const<'tcx> { + #[inline] pub fn ty(self) -> Ty<'tcx> { self.0.ty } + #[inline] pub fn val(self) -> ConstKind<'tcx> { self.0.val } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4e6be84ad7f..30fe3ffa7e3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -367,6 +367,16 @@ pub struct GeneratorInteriorTypeCause<'tcx> { pub expr: Option<hir::HirId>, } +// This type holds diagnostic information on generators and async functions across crate boundaries +// and is used to provide better error messages +#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)] +pub struct GeneratorDiagnosticData<'tcx> { + pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>, + pub hir_owner: DefId, + pub nodes_types: ItemLocalMap<Ty<'tcx>>, + pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>, +} + #[derive(TyEncodable, TyDecodable, Debug, HashStable)] pub struct TypeckResults<'tcx> { /// The `HirId::owner` all `ItemLocalId`s in this table are relative to. @@ -623,6 +633,28 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types } } + pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> { + let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| { + vec.iter() + .map(|item| { + GeneratorInteriorTypeCause { + ty: item.ty, + span: item.span, + scope_span: item.scope_span, + yield_span: item.yield_span, + expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment + } + }) + .collect::<Vec<_>>() + }); + GeneratorDiagnosticData { + generator_interior_types: generator_interior_type, + hir_owner: self.hir_owner.to_def_id(), + nodes_types: self.node_types.clone(), + adjustments: self.adjustments.clone(), + } + } + pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> { self.node_type_opt(id).unwrap_or_else(|| { bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id))) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f6d139fe59d..7cf2984a63f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1120,21 +1120,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { match st[i].abi() { Abi::Scalar(_) => Abi::Scalar(niche_scalar), Abi::ScalarPair(first, second) => { - // We need to use scalar_unit to reset the - // valid range to the maximal one for that - // primitive, because only the niche is - // guaranteed to be initialised, not the - // other primitive. + // Only the niche is guaranteed to be initialised, + // so use union layout for the other primitive. if offset.bytes() == 0 { - Abi::ScalarPair( - niche_scalar, - scalar_unit(second.primitive()), - ) + Abi::ScalarPair(niche_scalar, second.to_union()) } else { - Abi::ScalarPair( - scalar_unit(first.primitive()), - niche_scalar, - ) + Abi::ScalarPair(first.to_union(), niche_scalar) } } _ => Abi::Aggregate { sized: true }, @@ -1329,6 +1320,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; + let mut common_prim_initialized_in_all_variants = true; for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { bug!(); @@ -1336,7 +1328,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); let (field, offset) = match (fields.next(), fields.next()) { - (None, None) => continue, + (None, None) => { + common_prim_initialized_in_all_variants = false; + continue; + } (Some(pair), None) => pair, _ => { common_prim = None; @@ -1344,7 +1339,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } }; let prim = match field.abi { - Abi::Scalar(scalar) => scalar.primitive(), + Abi::Scalar(scalar) => { + common_prim_initialized_in_all_variants &= + matches!(scalar, Scalar::Initialized { .. }); + scalar.primitive() + } _ => { common_prim = None; break; @@ -1364,7 +1363,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } if let Some((prim, offset)) = common_prim { - let pair = self.scalar_pair(tag, scalar_unit(prim)); + let prim_scalar = if common_prim_initialized_in_all_variants { + scalar_unit(prim) + } else { + // Common prim might be uninit. + Scalar::Union { value: prim } + }; + let pair = self.scalar_pair(tag, prim_scalar); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index, &[0, 1]); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c2accea11ba..ec416722c21 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -36,7 +36,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::Node; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; @@ -67,8 +67,9 @@ pub use self::consts::{ }; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, - Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, + CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData, + GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, + UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef}; pub use self::list::List; @@ -130,6 +131,8 @@ pub struct ResolverOutputs { pub definitions: rustc_hir::definitions::Definitions, pub cstore: Box<CrateStoreDyn>, pub visibilities: FxHashMap<LocalDefId, Visibility>, + /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. + pub has_pub_restricted: bool, pub access_levels: AccessLevels, pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, pub maybe_unused_trait_imports: FxHashSet<LocalDefId>, @@ -316,22 +319,6 @@ impl<'tcx> DefIdTree for TyCtxt<'tcx> { } impl Visibility { - pub fn from_hir(visibility: &hir::Visibility<'_>, id: hir::HirId, tcx: TyCtxt<'_>) -> Self { - match visibility.node { - hir::VisibilityKind::Public => Visibility::Public, - hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)), - hir::VisibilityKind::Restricted { ref path, .. } => match path.res { - // If there is no resolution, `resolve` will have already reported an error, so - // assume that the visibility is public to avoid reporting more privacy errors. - Res::Err => Visibility::Public, - def => Visibility::Restricted(def.def_id()), - }, - hir::VisibilityKind::Inherited => { - Visibility::Restricted(tcx.parent_module(id).to_def_id()) - } - } - } - /// Returns `true` if an item with this visibility is accessible from the given block. pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool { let restriction = match self { @@ -1992,8 +1979,8 @@ impl<'tcx> TyCtxt<'tcx> { } fn opt_item_name(self, def_id: DefId) -> Option<Symbol> { - if def_id.index == CRATE_DEF_INDEX { - Some(self.crate_name(def_id.krate)) + if let Some(cnum) = def_id.as_crate_root() { + Some(self.crate_name(cnum)) } else { let def_key = self.def_key(def_id); match def_key.disambiguated_data.data { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index cac46ba25fe..38362a4cbb9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; -use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; @@ -335,9 +335,7 @@ pub trait PrettyPrinter<'tcx>: // If `def_id` is a direct or injected extern crate, return the // path to the crate followed by the path to the item within the crate. - if def_id.index == CRATE_DEF_INDEX { - let cnum = def_id.krate; - + if let Some(cnum) = def_id.as_crate_root() { if cnum == LOCAL_CRATE { return Ok((self.path_crate(cnum)?, true)); } @@ -2227,11 +2225,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { ty::BrNamed(_, _) => br.kind, ty::BrAnon(i) => { let name = region_map[&(i + 1)]; - ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) } ty::BrEnv => { let name = region_map[&0]; - ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) } }; self.tcx.mk_region(ty::ReLateBound( @@ -2257,7 +2255,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } }; do_continue(&mut self, name); - ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) } }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) @@ -2697,7 +2695,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let mut seen_defs: DefIdSet = Default::default(); for &cnum in tcx.crates(()).iter() { - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; + let def_id = cnum.as_def_id(); // Ignore crates that are not direct dependencies. match tcx.extern_crate(def_id) { diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 9e48c569c25..7629d7a8259 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -31,8 +31,11 @@ use crate::traits::{self, ImplSource}; use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; +use crate::ty::GeneratorDiagnosticData; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; +use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; +use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; @@ -49,13 +52,10 @@ use rustc_session::cstore::{CrateDepKind, CrateSource}; use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; -use rustc_target::abi; -use rustc_target::spec::PanicStrategy; - -use rustc_ast as ast; -use rustc_attr as attr; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::abi; +use rustc_target::spec::PanicStrategy; use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index d9b55563996..4c1160e21fe 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -61,7 +61,7 @@ pub trait TypeRelation<'tcx>: Sized { let tcx = self.tcx(); let opt_variances = tcx.variances_of(item_def_id); - relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst) + relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -135,29 +135,34 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>( } } +#[inline] pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - variances: Option<(DefId, &[ty::Variance])>, + a_subst: SubstsRef<'tcx>, + b_subst: SubstsRef<'tcx>, +) -> RelateResult<'tcx, SubstsRef<'tcx>> { + relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| { + relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) + })) +} + +pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( + relation: &mut R, + ty_def_id: DefId, + variances: &[ty::Variance], a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); - let mut cached_ty = None; + let mut cached_ty = None; let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { - let (variance, variance_info) = match variances { - Some((ty_def_id, variances)) => { - let variance = variances[i]; - let variance_info = if variance == ty::Invariant { - let ty = *cached_ty - .get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); - ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } - } else { - ty::VarianceDiagInfo::default() - }; - (variance, variance_info) - } - None => (ty::Invariant, ty::VarianceDiagInfo::default()), + let variance = variances[i]; + let variance_info = if variance == ty::Invariant { + let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); + ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } + } else { + ty::VarianceDiagInfo::default() }; relation.relate_with_variance(variance, variance_info, a, b) }); @@ -318,7 +323,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { - let substs = relate_substs(relation, None, a.substs, b.substs)?; + let substs = relate_substs(relation, a.substs, b.substs)?; Ok(ty::TraitRef { def_id: a.def_id, substs }) } } @@ -334,7 +339,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { - let substs = relate_substs(relation, None, a.substs, b.substs)?; + let substs = relate_substs(relation, a.substs, b.substs)?; Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) } } @@ -554,7 +559,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, None, a_substs, b_substs)?; + let substs = relate_substs(relation, a_substs, b_substs)?; Ok(tcx.mk_opaque(a_def_id, substs)) } @@ -742,7 +747,7 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { a: ty::ClosureSubsts<'tcx>, b: ty::ClosureSubsts<'tcx>, ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { - let substs = relate_substs(relation, None, a.substs, b.substs)?; + let substs = relate_substs(relation, a.substs, b.substs)?; Ok(ty::ClosureSubsts { substs }) } } @@ -753,7 +758,7 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { a: ty::GeneratorSubsts<'tcx>, b: ty::GeneratorSubsts<'tcx>, ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { - let substs = relate_substs(relation, None, a.substs, b.substs)?; + let substs = relate_substs(relation, a.substs, b.substs)?; Ok(ty::GeneratorSubsts { substs }) } } @@ -764,7 +769,7 @@ impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { a: SubstsRef<'tcx>, b: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { - relate_substs(relation, None, a, b) + relate_substs(relation, a, b) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 5c7910db362..4ef6ff1835f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -10,7 +10,6 @@ use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; use rustc_hir as hir; use rustc_hir::def::Namespace; -use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; use std::fmt; @@ -71,7 +70,7 @@ impl fmt::Debug for ty::BoundRegionKind { match *self { ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), ty::BrNamed(did, name) => { - if did.index == CRATE_DEF_INDEX { + if did.is_crate_root() { write!(f, "BrNamed({})", name) } else { write!(f, "BrNamed({:?}, {})", did, name) diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index a04ac338274..cee657e9da2 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -255,10 +255,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { func: fun, args, cleanup: None, - // FIXME(varkor): replace this with an uninhabitedness-based check. - // This requires getting access to the current module to call - // `tcx.is_ty_uninhabited_from`, which is currently tricky to do. - destination: if expr.ty.is_never() { + // The presence or absence of a return edge affects control-flow sensitive + // MIR checks and ultimately whether code is accepted or not. We can only + // omit the return edge if a return type is visibly uninhabited to a module + // that makes the call. + destination: if this.tcx.is_ty_uninhabited_from( + this.parent_module, + expr.ty, + this.param_env, + ) { None } else { Some((destination, success)) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 901635dc488..3c51f791862 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -350,6 +350,7 @@ struct Builder<'a, 'tcx> { def_id: DefId, hir_id: hir::HirId, + parent_module: DefId, check_overflow: bool, fn_span: Span, arg_count: usize, @@ -807,15 +808,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); let lint_level = LintLevel::Explicit(hir_id); + let param_env = tcx.param_env(def.did); let mut builder = Builder { thir, tcx, infcx, typeck_results: tcx.typeck_opt_const_arg(def), region_scope_tree: tcx.region_scope_tree(def.did), - param_env: tcx.param_env(def.did), + param_env, def_id: def.did.to_def_id(), hir_id, + parent_module: tcx.parent_module(hir_id).to_def_id(), check_overflow, cfg: CFG { basic_blocks: IndexVec::new() }, fn_span: span, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 13b49256d48..691f4fb0e54 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -313,9 +313,7 @@ struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - // FIXME(eddyb) avoid cloning this field more than once, - // by accessing it through `ecx` instead. - local_decls: IndexVec<Local, LocalDecl<'tcx>>, + local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>, // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store // the last known `SourceInfo` here and just keep revisiting it. source_info: Option<SourceInfo>, @@ -361,10 +359,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let substs = &InternalSubsts::identity_for_item(tcx, def_id); let param_env = tcx.param_env_reveal_all_normalized(def_id); - let span = tcx.def_span(def_id); - // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts - // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in - // `layout_of` query invocations. let can_const_prop = CanConstProp::check(tcx, param_env, body); let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len()); for (l, mode) in can_const_prop.iter_enumerated() { @@ -374,7 +368,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let mut ecx = InterpCx::new( tcx, - span, + tcx.def_span(def_id), param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), ); @@ -405,10 +399,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ecx, tcx, param_env, - // FIXME(eddyb) avoid cloning this field more than once, - // by accessing it through `ecx` instead. - //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it - local_decls: body.local_decls.clone(), + local_decls: &dummy_body.local_decls, source_info: None, } } @@ -511,7 +502,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = r?; // We need the type of the LHS. We cannot use `place_layout` as that is the type // of the result, which for checked binops is not the same! - let left_ty = left.ty(&self.local_decls, self.tcx); + let left_ty = left.ty(self.local_decls, self.tcx); let left_size = self.ecx.layout_of(left_ty).ok()?.size; let right_size = r.layout.size; let r_bits = r.to_scalar().ok(); diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index d6331a88c5b..4945c10c9aa 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -308,10 +308,8 @@ struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - // FIXME(eddyb) avoid cloning these two fields more than once, - // by accessing them through `ecx` instead. - source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>, - local_decls: IndexVec<Local, LocalDecl<'tcx>>, + source_scopes: &'mir IndexVec<SourceScope, SourceScopeData<'tcx>>, + local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>, // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store // the last known `SourceInfo` here and just keep revisiting it. source_info: Option<SourceInfo>, @@ -357,10 +355,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let substs = &InternalSubsts::identity_for_item(tcx, def_id); let param_env = tcx.param_env_reveal_all_normalized(def_id); - let span = tcx.def_span(def_id); - // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts - // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in - // `layout_of` query invocations. let can_const_prop = CanConstProp::check(tcx, param_env, body); let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len()); for (l, mode) in can_const_prop.iter_enumerated() { @@ -370,7 +364,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let mut ecx = InterpCx::new( tcx, - span, + tcx.def_span(def_id), param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), ); @@ -401,11 +395,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ecx, tcx, param_env, - // FIXME(eddyb) avoid cloning these two fields more than once, - // by accessing them through `ecx` instead. - source_scopes: body.source_scopes.clone(), - //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it - local_decls: body.local_decls.clone(), + source_scopes: &dummy_body.source_scopes, + local_decls: &dummy_body.local_decls, source_info: None, } } @@ -435,7 +426,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> { - source_info.scope.lint_root(&self.source_scopes) + source_info.scope.lint_root(self.source_scopes) } fn use_ecx<F, T>(&mut self, f: F) -> Option<T> @@ -572,7 +563,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = r?; // We need the type of the LHS. We cannot use `place_layout` as that is the type // of the result, which for checked binops is not the same! - let left_ty = left.ty(&self.local_decls, self.tcx); + let left_ty = left.ty(self.local_decls, self.tcx); let left_size = self.ecx.layout_of(left_ty).ok()?.size; let right_size = r.layout.size; let r_bits = r.to_scalar().ok(); diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 740a2168b41..2380391d09a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -77,17 +77,30 @@ pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn let mut cnt = 0; let validate = tcx.sess.opts.debugging_opts.validate_mir; + let overridden_passes = &tcx.sess.opts.debugging_opts.mir_enable_passes; + trace!(?overridden_passes); if validate { validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase)); } for pass in passes { - if !pass.is_enabled(&tcx.sess) { - continue; - } - let name = pass.name(); + + if let Some((_, polarity)) = overridden_passes.iter().rev().find(|(s, _)| s == &*name) { + trace!( + pass = %name, + "{} as requested by flag", + if *polarity { "Running" } else { "Not running" }, + ); + if !polarity { + continue; + } + } else { + if !pass.is_enabled(&tcx.sess) { + continue; + } + } let dump_enabled = pass.is_mir_dump_enabled(); if dump_enabled { diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index c4ffb19f87a..16774198879 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathDataName; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::SymbolExportLevel; @@ -335,10 +335,10 @@ fn compute_codegen_unit_name( let mut cgu_def_id = None; // Walk backwards from the item we want to find the module for. loop { - if current_def_id.index == CRATE_DEF_INDEX { + if current_def_id.is_crate_root() { if cgu_def_id.is_none() { // If we have not found a module yet, take the crate root. - cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX }); + cgu_def_id = Some(def_id.krate.as_def_id()); } break; } else if tcx.def_kind(current_def_id) == DefKind::Mod { diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 5ee9c339bb7..02749088c31 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -100,21 +100,16 @@ rustc_data_structures::static_assert_size!(LazyTokenStreamImpl, 144); impl CreateTokenStream for LazyTokenStreamImpl { fn create_token_stream(&self) -> AttrAnnotatedTokenStream { - // The token produced by the final call to `{,inlined_}next` or - // `{,inlined_}next_desugared` was not actually consumed by the - // callback. The combination of chaining the initial token and using - // `take` produces the desired result - we produce an empty - // `TokenStream` if no calls were made, and omit the final token - // otherwise. + // The token produced by the final call to `{,inlined_}next` was not + // actually consumed by the callback. The combination of chaining the + // initial token and using `take` produces the desired result - we + // produce an empty `TokenStream` if no calls were made, and omit the + // final token otherwise. let mut cursor_snapshot = self.cursor_snapshot.clone(); let tokens = std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1)) .chain((0..self.num_calls).map(|_| { - let token = if cursor_snapshot.desugar_doc_comments { - cursor_snapshot.next_desugared() - } else { - cursor_snapshot.next() - }; + let token = cursor_snapshot.next(cursor_snapshot.desugar_doc_comments); (FlatToken::Token(token.0), token.1) })) .take(self.num_calls); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index cb6be8f412c..1686c5873e1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -123,8 +123,8 @@ pub struct Parser<'a> { pub capture_cfg: bool, restrictions: Restrictions, expected_tokens: Vec<TokenType>, - // Important: This must only be advanced from `next_tok` - // to ensure that `token_cursor.num_next_calls` is updated properly + // Important: This must only be advanced from `bump` to ensure that + // `token_cursor.num_next_calls` is updated properly. token_cursor: TokenCursor, desugar_doc_comments: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is @@ -150,6 +150,11 @@ pub struct Parser<'a> { pub current_closure: Option<ClosureSpans>, } +// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure +// it doesn't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(Parser<'_>, 328); + /// Stores span information about a closure. #[derive(Clone)] pub struct ClosureSpans { @@ -203,12 +208,15 @@ impl<'a> Drop for Parser<'a> { #[derive(Clone)] struct TokenCursor { + // The current (innermost) frame. `frame` and `stack` could be combined, + // but it's faster to have them separately to access `frame` directly + // rather than via something like `stack.last().unwrap()` or + // `stack[stack.len() - 1]`. frame: TokenCursorFrame, + // Additional frames that enclose `frame`. stack: Vec<TokenCursorFrame>, desugar_doc_comments: bool, - // Counts the number of calls to `{,inlined_}next` or - // `{,inlined_}next_desugared`, depending on whether - // `desugar_doc_comments` is set. + // Counts the number of calls to `{,inlined_}next`. num_next_calls: usize, // During parsing, we may sometimes need to 'unglue' a // glued token into two component tokens @@ -238,73 +246,60 @@ struct TokenCursor { struct TokenCursorFrame { delim: token::DelimToken, span: DelimSpan, - open_delim: bool, tree_cursor: tokenstream::Cursor, - close_delim: bool, } impl TokenCursorFrame { fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self { - TokenCursorFrame { - delim, - span, - open_delim: false, - tree_cursor: tts.into_trees(), - close_delim: false, - } + TokenCursorFrame { delim, span, tree_cursor: tts.into_trees() } } } impl TokenCursor { - fn next(&mut self) -> (Token, Spacing) { - self.inlined_next() + fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) { + self.inlined_next(desugar_doc_comments) } /// This always-inlined version should only be used on hot code paths. #[inline(always)] - fn inlined_next(&mut self) -> (Token, Spacing) { + fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) { loop { - let (tree, spacing) = if !self.frame.open_delim { - self.frame.open_delim = true; - TokenTree::open_tt(self.frame.span, self.frame.delim).into() - } else if let Some(tree) = self.frame.tree_cursor.next_with_spacing() { - tree - } else if !self.frame.close_delim { - self.frame.close_delim = true; - TokenTree::close_tt(self.frame.span, self.frame.delim).into() + // FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will + // need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be + // removed, as well as the loop. + if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing_ref() { + match tree { + &TokenTree::Token(ref token) => match (desugar_doc_comments, token) { + (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => { + return self.desugar(attr_style, data, span); + } + _ => return (token.clone(), *spacing), + }, + &TokenTree::Delimited(sp, delim, ref tts) => { + // Set `open_delim` to true here because we deal with it immediately. + let frame = TokenCursorFrame::new(sp, delim, tts.clone()); + self.stack.push(mem::replace(&mut self.frame, frame)); + if delim != DelimToken::NoDelim { + return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone); + } + // No open delimeter to return; continue on to the next iteration. + } + }; } else if let Some(frame) = self.stack.pop() { + let delim = self.frame.delim; + let span = self.frame.span; self.frame = frame; - continue; - } else { - (TokenTree::Token(Token::new(token::Eof, DUMMY_SP)), Spacing::Alone) - }; - - match tree { - TokenTree::Token(token) => { - return (token, spacing); - } - TokenTree::Delimited(sp, delim, tts) => { - let frame = TokenCursorFrame::new(sp, delim, tts); - self.stack.push(mem::replace(&mut self.frame, frame)); + if delim != DelimToken::NoDelim { + return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone); } + // No close delimiter to return; continue on to the next iteration. + } else { + return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone); } } } - fn next_desugared(&mut self) -> (Token, Spacing) { - self.inlined_next_desugared() - } - - /// This always-inlined version should only be used on hot code paths. - #[inline(always)] - fn inlined_next_desugared(&mut self) -> (Token, Spacing) { - let (data, attr_style, sp) = match self.inlined_next() { - (Token { kind: token::DocComment(_, attr_style, data), span }, _) => { - (data, attr_style, span) - } - tok => return tok, - }; - + fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) { // Searches for the occurrences of `"#*` and returns the minimum number of `#`s // required to wrap the text. let mut num_of_hashes = 0; @@ -318,14 +313,14 @@ impl TokenCursor { num_of_hashes = cmp::max(num_of_hashes, count); } - let delim_span = DelimSpan::from_single(sp); + let delim_span = DelimSpan::from_single(span); let body = TokenTree::Delimited( delim_span, token::Bracket, [ - TokenTree::token(token::Ident(sym::doc, false), sp), - TokenTree::token(token::Eq, sp), - TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), sp), + TokenTree::token(token::Ident(sym::doc, false), span), + TokenTree::token(token::Eq, span), + TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), span), ] .iter() .cloned() @@ -338,12 +333,12 @@ impl TokenCursor { delim_span, token::NoDelim, if attr_style == AttrStyle::Inner { - [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body] + [TokenTree::token(token::Pound, span), TokenTree::token(token::Not, span), body] .iter() .cloned() .collect::<TokenStream>() } else { - [TokenTree::token(token::Pound, sp), body] + [TokenTree::token(token::Pound, span), body] .iter() .cloned() .collect::<TokenStream>() @@ -351,7 +346,7 @@ impl TokenCursor { ), )); - self.next() + self.next(/* desugar_doc_comments */ false) } } @@ -436,9 +431,9 @@ impl<'a> Parser<'a> { desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { - let mut start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens); - start_frame.open_delim = true; - start_frame.close_delim = true; + // Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and + // `delim` arguments here are never used. + let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens); let mut parser = Parser { sess, @@ -476,33 +471,6 @@ impl<'a> Parser<'a> { parser } - #[inline] - fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) { - loop { - let (mut next, spacing) = if self.desugar_doc_comments { - self.token_cursor.inlined_next_desugared() - } else { - self.token_cursor.inlined_next() - }; - self.token_cursor.num_next_calls += 1; - // We've retrieved an token from the underlying - // cursor, so we no longer need to worry about - // an unglued token. See `break_and_eat` for more details - self.token_cursor.break_last_token = false; - if next.span.is_dummy() { - // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = fallback_span.with_ctxt(next.span.ctxt()); - } - if matches!( - next.kind, - token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) - ) { - continue; - } - return (next, spacing); - } - } - pub fn unexpected<T>(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), @@ -697,7 +665,7 @@ impl<'a> Parser<'a> { // // If we consume any additional tokens, then this token // is not needed (we'll capture the entire 'glued' token), - // and `next_tok` will set this field to `None` + // and `bump` will set this field to `None` self.token_cursor.break_last_token = true; // Use the spacing of the glued token as the spacing // of the unglued second token. @@ -1019,12 +987,6 @@ impl<'a> Parser<'a> { /// This always-inlined version should only be used on hot code paths. #[inline(always)] fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) { - // Bumping after EOF is a bad sign, usually an infinite loop. - if self.prev_token.kind == TokenKind::Eof { - let msg = "attempted to bump the parser past EOF (may be stuck in a loop)"; - self.span_bug(self.token.span, msg); - } - // Update the current and previous tokens. self.prev_token = mem::replace(&mut self.token, next_token); self.token_spacing = next_spacing; @@ -1035,8 +997,24 @@ impl<'a> Parser<'a> { /// Advance the parser by one token. pub fn bump(&mut self) { - let next_token = self.next_tok(self.token.span); - self.inlined_bump_with(next_token); + // Note: destructuring here would give nicer code, but it was found in #96210 to be slower + // than `.0`/`.1` access. + let mut next = self.token_cursor.inlined_next(self.desugar_doc_comments); + self.token_cursor.num_next_calls += 1; + // We've retrieved an token from the underlying + // cursor, so we no longer need to worry about + // an unglued token. See `break_and_eat` for more details + self.token_cursor.break_last_token = false; + if next.0.span.is_dummy() { + // Tweak the location for better diagnostics, but keep syntactic context intact. + let fallback_span = self.token.span; + next.0.span = fallback_span.with_ctxt(next.0.span.ctxt()); + } + debug_assert!(!matches!( + next.0.kind, + token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) + )); + self.inlined_bump_with(next) } /// Look-ahead `dist` tokens of `self.token` and get access to that token there. @@ -1069,7 +1047,7 @@ impl<'a> Parser<'a> { let mut i = 0; let mut token = Token::dummy(); while i < dist { - token = cursor.next().0; + token = cursor.next(/* desugar_doc_comments */ false).0; if matches!( token.kind, token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) @@ -1217,24 +1195,28 @@ impl<'a> Parser<'a> { pub(crate) fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { - let depth = self.token_cursor.stack.len(); + // Grab the tokens from this frame. + let frame = &self.token_cursor.frame; + let stream = frame.tree_cursor.stream.clone(); + let span = frame.span; + let delim = frame.delim; - // We keep advancing the token cursor until we hit - // the matching `CloseDelim` token. - while !(depth == self.token_cursor.stack.len() - && matches!(self.token.kind, token::CloseDelim(_))) - { + // Advance the token cursor through the entire delimited + // sequence. After getting the `OpenDelim` we are *within* the + // delimited sequence, i.e. at depth `d`. After getting the + // matching `CloseDelim` we are *after* the delimited sequence, + // i.e. at depth `d - 1`. + let target_depth = self.token_cursor.stack.len() - 1; + loop { // Advance one token at a time, so `TokenCursor::next()` // can capture these tokens if necessary. self.bump(); + if self.token_cursor.stack.len() == target_depth { + debug_assert!(matches!(self.token.kind, token::CloseDelim(_))); + break; + } } - // We are still inside the frame corresponding - // to the delimited stream we captured, so grab - // the tokens from this frame. - let frame = &self.token_cursor.frame; - let stream = frame.tree_cursor.stream.clone(); - let span = frame.span; - let delim = frame.delim; + // Consume close delimiter self.bump(); TokenTree::Delimited(span, delim, stream) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index b45bca3d2e0..691bfdb01a4 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -11,8 +11,10 @@ use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle}; impl<'a> Parser<'a> { /// Checks whether a non-terminal may begin with a particular token. /// - /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that - /// token. Be conservative (return true) if not sure. + /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with + /// that token. Be conservative (return true) if not sure. Inlined because it has a single call + /// site. + #[inline] pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { @@ -95,7 +97,9 @@ impl<'a> Parser<'a> { } } - /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). + /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call + /// site. + #[inline] pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`) // needs to have them force-captured here. diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 261ea0b4deb..b661f6f9d72 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -45,8 +45,6 @@ struct MarkSymbolVisitor<'tcx> { live_symbols: FxHashSet<LocalDefId>, repr_has_repr_c: bool, in_pat: bool, - inherited_pub_visibility: bool, - pub_visibility: bool, ignore_variant_stack: Vec<DefId>, // maps from tuple struct constructors to tuple struct items struct_constructors: FxHashMap<LocalDefId, LocalDefId>, @@ -284,33 +282,23 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } let had_repr_c = self.repr_has_repr_c; - let had_inherited_pub_visibility = self.inherited_pub_visibility; - let had_pub_visibility = self.pub_visibility; self.repr_has_repr_c = false; - self.inherited_pub_visibility = false; - self.pub_visibility = false; match node { - Node::Item(item) => { - self.pub_visibility = item.vis.node.is_pub(); + Node::Item(item) => match item.kind { + hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { + let def = self.tcx.adt_def(item.def_id); + self.repr_has_repr_c = def.repr().c(); - match item.kind { - hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id); - self.repr_has_repr_c = def.repr().c(); - - intravisit::walk_item(self, &item); - } - hir::ItemKind::Enum(..) => { - self.inherited_pub_visibility = self.pub_visibility; - - intravisit::walk_item(self, &item); - } - hir::ItemKind::ForeignMod { .. } => {} - _ => { - intravisit::walk_item(self, &item); - } + intravisit::walk_item(self, &item); } - } + hir::ItemKind::Enum(..) => { + intravisit::walk_item(self, &item); + } + hir::ItemKind::ForeignMod { .. } => {} + _ => { + intravisit::walk_item(self, &item); + } + }, Node::TraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } @@ -322,8 +310,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } _ => {} } - self.pub_visibility = had_pub_visibility; - self.inherited_pub_visibility = had_inherited_pub_visibility; self.repr_has_repr_c = had_repr_c; } @@ -354,14 +340,19 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { _: hir::HirId, _: rustc_span::Span, ) { + let tcx = self.tcx; let has_repr_c = self.repr_has_repr_c; - let inherited_pub_visibility = self.inherited_pub_visibility; - let pub_visibility = self.pub_visibility; - let live_fields = def.fields().iter().filter(|f| { - has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub())) + let live_fields = def.fields().iter().filter_map(|f| { + let def_id = tcx.hir().local_def_id(f.hir_id); + if has_repr_c { + return Some(def_id); + } + if !tcx.visibility(f.hir_id.owner).is_public() { + return None; + } + if tcx.visibility(def_id).is_public() { Some(def_id) } else { None } }); - let hir = self.tcx.hir(); - self.live_symbols.extend(live_fields.map(|f| hir.local_def_id(f.hir_id))); + self.live_symbols.extend(live_fields); intravisit::walk_struct_def(self, def); } @@ -602,8 +593,6 @@ fn live_symbols_and_ignored_derived_traits<'tcx>( live_symbols: Default::default(), repr_has_repr_c: false, in_pat: false, - inherited_pub_visibility: false, - pub_visibility: false, ignore_variant_stack: vec![], struct_constructors, ignored_derived_traits: FxHashMap::default(), diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 5a1373ad1a2..db083d0453b 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,21 +1,18 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ForeignItem, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID}; -use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{DefIdTree, TyCtxt}; use rustc_session::config::{CrateType, EntryFnType}; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; -struct EntryContext<'a, 'tcx> { - session: &'a Session, - - map: Map<'tcx>, +struct EntryContext<'tcx> { + tcx: TyCtxt<'tcx>, /// The function that has attribute named `main`. attr_main_fn: Option<(LocalDefId, Span)>, @@ -28,10 +25,9 @@ struct EntryContext<'a, 'tcx> { non_main_fns: Vec<Span>, } -impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for EntryContext<'tcx> { fn visit_item(&mut self, item: &'tcx Item<'tcx>) { - let def_key = self.map.def_key(item.def_id); - let at_root = def_key.parent == Some(CRATE_DEF_INDEX); + let at_root = self.tcx.local_parent(item.def_id) == Some(CRATE_DEF_ID); find_item(item, self, at_root); } @@ -60,13 +56,8 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { return None; } - let mut ctxt = EntryContext { - session: tcx.sess, - map: tcx.hir(), - attr_main_fn: None, - start_fn: None, - non_main_fns: Vec::new(), - }; + let mut ctxt = + EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; tcx.hir().visit_all_item_likes(&mut ctxt); @@ -75,11 +66,11 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs` // (with `ast::Item`), so make sure to keep them in sync. -fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) -> EntryPointType { - let attrs = ctxt.map.attrs(item.hir_id()); - if ctxt.session.contains_name(attrs, sym::start) { +fn entry_point_type(ctxt: &EntryContext<'_>, item: &Item<'_>, at_root: bool) -> EntryPointType { + let attrs = ctxt.tcx.hir().attrs(item.hir_id()); + if ctxt.tcx.sess.contains_name(attrs, sym::start) { EntryPointType::Start - } else if ctxt.session.contains_name(attrs, sym::rustc_main) { + } else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { if at_root { @@ -98,16 +89,16 @@ fn throw_attr_err(sess: &Session, span: Span, attr: &str) { .emit(); } -fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { +fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_>, at_root: bool) { match entry_point_type(ctxt, item, at_root) { EntryPointType::None => (), _ if !matches!(item.kind, ItemKind::Fn(..)) => { - let attrs = ctxt.map.attrs(item.hir_id()); - if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) { - throw_attr_err(&ctxt.session, attr.span, "start"); + let attrs = ctxt.tcx.hir().attrs(item.hir_id()); + if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::start) { + throw_attr_err(&ctxt.tcx.sess, attr.span, "start"); } - if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) { - throw_attr_err(&ctxt.session, attr.span, "rustc_main"); + if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::rustc_main) { + throw_attr_err(&ctxt.tcx.sess, attr.span, "rustc_main"); } } EntryPointType::MainNamed => (), @@ -119,7 +110,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { ctxt.attr_main_fn = Some((item.def_id, item.span)); } else { struct_span_err!( - ctxt.session, + ctxt.tcx.sess, item.span, E0137, "multiple functions with a `#[main]` attribute" @@ -133,7 +124,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { if ctxt.start_fn.is_none() { ctxt.start_fn = Some((item.def_id, item.span)); } else { - struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions") + struct_span_err!(ctxt.tcx.sess, item.span, E0138, "multiple `start` functions") .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here") .span_label(item.span, "multiple `start` functions") .emit(); @@ -142,7 +133,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { } } -fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> { +fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) } else if let Some((def_id, _)) = visitor.attr_main_fn { @@ -177,7 +168,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } } -fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { +fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { let sp = tcx.def_span(CRATE_DEF_ID); if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 56755d68686..379a6827c8a 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId}; @@ -89,7 +89,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.owner = Some(owner); walk(self); - if owner.local_def_index == CRATE_DEF_INDEX { + if owner == CRATE_DEF_ID { return; } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 01ba9e35c24..35a858cb86c 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant}; @@ -703,7 +703,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else { return; }; - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; + let def_id = cnum.as_def_id(); self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0ce97de4134..5f9a0357557 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -296,28 +296,6 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib } //////////////////////////////////////////////////////////////////////////////// -/// Visitor used to determine if pub(restricted) is used anywhere in the crate. -/// -/// This is done so that `private_in_public` warnings can be turned into hard errors -/// in crates that have been updated to use pub(restricted). -//////////////////////////////////////////////////////////////////////////////// -struct PubRestrictedVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - has_pub_restricted: bool, -} - -impl<'tcx> Visitor<'tcx> for PubRestrictedVisitor<'tcx> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) { - self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted(); - } -} - -//////////////////////////////////////////////////////////////////////////////// /// Visitor used to determine impl visibility and reachability. //////////////////////////////////////////////////////////////////////////////// @@ -682,7 +660,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { self.update_with_hir_id(ctor_hir_id, item_level); } for field in def.fields() { - if field.vis.node.is_pub() { + let def_id = self.tcx.hir().local_def_id(field.hir_id); + let vis = self.tcx.visibility(def_id); + if vis.is_public() { self.update_with_hir_id(field.hir_id, item_level); } } @@ -1361,7 +1341,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // .. and it corresponds to a private type in the AST (this returns // `None` for type parameters). match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) { - Some(Node::Item(item)) => !item.vis.node.is_pub(), + Some(Node::Item(_)) => !self.tcx.visibility(did).is_public(), Some(_) | None => false, } } else { @@ -1383,8 +1363,8 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } - fn item_is_public(&self, def_id: LocalDefId, vis: &hir::Visibility<'_>) -> bool { - self.access_levels.is_reachable(def_id) || vis.node.is_pub() + fn item_is_public(&self, def_id: LocalDefId) -> bool { + self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public() } } @@ -1519,8 +1499,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) - if self - .item_is_public(impl_item.def_id, &impl_item.vis) => + if self.item_is_public(impl_item.def_id) => { intravisit::walk_impl_item(self, impl_item) } @@ -1591,7 +1570,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::TyAlias(..) => return, // Not at all public, so we don't care. - _ if !self.item_is_public(item.def_id, &item.vis) => { + _ if !self.item_is_public(item.def_id) => { return; } @@ -1655,7 +1634,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { - if s.vis.node.is_pub() || self.in_variant { + let def_id = self.tcx.hir().local_def_id(s.hir_id); + let vis = self.tcx.visibility(def_id); + if vis.is_public() || self.in_variant { intravisit::walk_field_def(self, s); } } @@ -1680,7 +1661,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { item_def_id: LocalDefId, /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, - has_pub_restricted: bool, has_old_errors: bool, in_assoc_ty: bool, } @@ -1769,7 +1749,10 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr); let span = self.tcx.def_span(self.item_def_id.to_def_id()); - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { + if self.has_old_errors + || self.in_assoc_ty + || self.tcx.resolutions(()).has_pub_restricted + { let mut err = if kind == "trait" { struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg()) } else { @@ -1828,7 +1811,6 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { struct PrivateItemsInPublicInterfacesVisitor<'tcx> { tcx: TyCtxt<'tcx>, - has_pub_restricted: bool, old_error_set_ancestry: LocalDefIdSet, } @@ -1842,7 +1824,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> { tcx: self.tcx, item_def_id: def_id, required_visibility, - has_pub_restricted: self.has_pub_restricted, has_old_errors: self.old_error_set_ancestry.contains(&def_id), in_assoc_ty: false, } @@ -1994,19 +1975,16 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility { match tcx.hir().get(hir_id) { // Unique types created for closures participate in type privacy checking. // They have visibilities inherited from the module they are defined in. - Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { - ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()) - } - // - AST lowering may clone `use` items and the clones don't + Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) + // - AST lowering creates dummy `use` items which don't // get their entries in the resolver's visibility table. // - AST lowering also creates opaque type items with inherited visibilities. // Visibility on them should have no effect, but to avoid the visibility // query failing on some items, we provide it for opaque types as well. - Node::Item(hir::Item { - vis, - kind: hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..), + | Node::Item(hir::Item { + kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..), .. - }) => ty::Visibility::from_hir(vis, hir_id, tcx), + }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()), // Visibilities of trait impl items are inherited from their traits // and are not filled in resolve. Node::ImplItem(impl_item) => { @@ -2083,12 +2061,6 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { }; tcx.hir().walk_toplevel_module(&mut visitor); - let has_pub_restricted = { - let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false }; - tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor); - pub_restricted_visitor.has_pub_restricted - }; - let mut old_error_set_ancestry = HirIdSet::default(); for mut id in visitor.old_error_set.iter().copied() { loop { @@ -2106,7 +2078,6 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { // Check for private types and traits in public interfaces. let mut visitor = PrivateItemsInPublicInterfacesVisitor { tcx, - has_pub_restricted, // Only definition IDs are ever searched in `old_error_set_ancestry`, // so we can filter away all non-definition IDs at this point. old_error_set_ancestry: old_error_set_ancestry diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index acccf43f062..b20aa7b5346 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -1,7 +1,7 @@ use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathData; use rustc_middle::ty::{TyCtxt, WithOptConstParam}; use rustc_query_system::query::QueryCache; @@ -143,7 +143,7 @@ impl SpecIntoSelfProfilingString for CrateNum { &self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>, ) -> StringId { - builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX }) + builder.def_id_to_string_id(self.as_def_id()) } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 063b15e643d..291b6645d9a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -23,7 +23,7 @@ use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::SyntaxExtension; use rustc_expand::expand::AstFragment; use rustc_hir::def::{self, *}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::bug; use rustc_middle::metadata::ModChild; @@ -140,8 +140,8 @@ impl<'a> Resolver<'a> { let parent = def_key.parent.map(|index| { self.get_nearest_non_block_module(DefId { index, krate: def_id.krate }) }); - let name = if def_id.index == CRATE_DEF_INDEX { - self.cstore().crate_name(def_id.krate) + let name = if let Some(cnum) = def_id.as_crate_root() { + self.cstore().crate_name(cnum) } else { def_key.disambiguated_data.data.get_opt_name().expect("module without name") }; @@ -250,7 +250,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { match vis.kind { ast::VisibilityKind::Public => Ok(ty::Visibility::Public), ast::VisibilityKind::Crate(..) => { - Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))) + Ok(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())) } ast::VisibilityKind::Inherited => { Ok(match self.parent_scope.module.kind { @@ -265,6 +265,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }) } ast::VisibilityKind::Restricted { ref path, id, .. } => { + // Make `PRIVATE_IN_PUBLIC` lint a hard error. + self.r.has_pub_restricted = true; // For visibilities we are not ready to provide correct implementation of "uniform // paths" right now, so on 2018 edition we only allow module-relative paths for now. // On 2015 edition visibilities are resolved as crate-relative by default, @@ -458,6 +460,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; + self.r.visibilities.insert(self.r.local_def_id(id), vis); + if id1 != ast::DUMMY_NODE_ID { + self.r.visibilities.insert(self.r.local_def_id(id1), vis); + } + if id2 != ast::DUMMY_NODE_ID { + self.r.visibilities.insert(self.r.local_def_id(id2), vis); + } + if nested { // Correctly handle `self` if source.ident.name == kw::SelfLower { @@ -580,6 +590,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; + self.r.visibilities.insert(self.r.local_def_id(id), vis); self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis); } ast::UseTreeKind::Nested(ref items) => { @@ -758,7 +769,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let mut ctor_vis = if vis == ty::Visibility::Public && self.r.session.contains_name(&item.attrs, sym::non_exhaustive) { - ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)) + ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) } else { vis }; @@ -1107,7 +1118,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { root_span: span, span, module_path: Vec::new(), - vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))), + vis: Cell::new(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())), used: Cell::new(false), }) }; @@ -1243,7 +1254,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let vis = if is_macro_export { ty::Visibility::Public } else { - ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)) + ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) }; let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas); self.r.set_binding_parent_module(binding, parent_scope.module); @@ -1489,7 +1500,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let ctor_vis = if vis == ty::Visibility::Public && self.r.session.contains_name(&variant.attrs, sym::non_exhaustive) { - ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)) + ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) } else { vis }; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f3b8c1e266c..9bbecf104e5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -10,7 +10,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::PrimTy; use rustc_middle::bug; use rustc_middle::ty::DefIdTree; @@ -1014,7 +1014,7 @@ impl<'a> Resolver<'a> { } ResolutionError::InvalidAsmSym => { let mut err = self.session.struct_span_err(span, "invalid `sym` operand"); - err.span_label(span, &format!("is a local variable")); + err.span_label(span, "is a local variable"); err.help("`sym` operands must refer to either a function or a static"); err } @@ -1167,7 +1167,7 @@ impl<'a> Resolver<'a> { } Scope::ExternPrelude => { suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { - let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)); + let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res)) })); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9bc5d63ca17..7635ad9bd87 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -19,7 +19,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_middle::ty::DefIdTree; use rustc_middle::{bug, span_bug}; @@ -1696,7 +1696,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { "invalid lifetime parameter name: `{}`", param.ident, ) - .span_label(param.ident.span, format!("'static is a reserved lifetime name")) + .span_label(param.ident.span, "'static is a reserved lifetime name") .emit(); continue; } @@ -2751,7 +2751,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // trait to resolve. In that case, we leave the `B` // segment to be resolved by type-check. return Ok(Some(PartialRes::with_unresolved_segments( - Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)), + Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()), path.len(), ))); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 0bae141ce26..d77cc917e2f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -20,7 +20,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::PrimTy; use rustc_session::parse::feature_err; use rustc_span::edition::Edition; @@ -352,7 +352,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } }) .collect::<Vec<_>>(); - let crate_def_id = DefId::local(CRATE_DEF_INDEX); + let crate_def_id = CRATE_DEF_ID.to_def_id(); if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) { let mut enum_candidates: Vec<_> = self .r @@ -1332,10 +1332,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { names.extend(extern_prelude.iter().flat_map(|(ident, _)| { self.r.crate_loader.maybe_process_path_extern(ident.name).and_then( |crate_id| { - let crate_mod = Res::Def( - DefKind::Mod, - DefId { krate: crate_id, index: CRATE_DEF_INDEX }, - ); + let crate_mod = + Res::Def(DefKind::Mod, crate_id.as_def_id()); if filter_fn(crate_mod) { Some(TypoSuggestion::typo_from_res( diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index d5f2e2db1e3..ce3069265d0 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -685,8 +685,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: hir::HirId, ) { let name = match fk { - intravisit::FnKind::ItemFn(id, _, _, _) => id.name, - intravisit::FnKind::Method(id, _, _) => id.name, + intravisit::FnKind::ItemFn(id, _, _) => id.name, + intravisit::FnKind::Method(id, _) => id.name, intravisit::FnKind::Closure => sym::closure, }; let name = name.as_str(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index eed54370e23..cca1f102586 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -38,7 +38,7 @@ use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId}; -use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; @@ -796,7 +796,7 @@ impl<'a> NameBinding<'a> { NameBindingKind::Module(&ModuleData { kind: ModuleKind::Def(DefKind::Mod, def_id, _), .. - }) => def_id.index == CRATE_DEF_INDEX, + }) => def_id.is_crate_root(), _ => false, } } @@ -934,6 +934,7 @@ pub struct Resolver<'a> { glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, /// Visibilities in "lowered" form, for all entities that have them. visibilities: FxHashMap<LocalDefId, ty::Visibility>, + has_pub_restricted: bool, used_imports: FxHashSet<NodeId>, maybe_unused_trait_imports: FxHashSet<LocalDefId>, maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, @@ -1248,18 +1249,17 @@ impl<'a> Resolver<'a> { ); let definitions = Definitions::new(session.local_stable_crate_id(), krate.spans.inner_span); - let root = definitions.get_root_def(); let mut visibilities = FxHashMap::default(); visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public); let mut def_id_to_node_id = IndexVec::default(); - assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root); + assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = FxHashMap::default(); - node_id_to_def_id.insert(CRATE_NODE_ID, root); + node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID); let mut invocation_parents = FxHashMap::default(); - invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential)); + invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential)); let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session .opts @@ -1314,6 +1314,7 @@ impl<'a> Resolver<'a> { glob_map: Default::default(), visibilities, + has_pub_restricted: false, used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), maybe_unused_extern_crates: Vec::new(), @@ -1424,6 +1425,7 @@ impl<'a> Resolver<'a> { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; let visibilities = self.visibilities; + let has_pub_restricted = self.has_pub_restricted; let extern_crate_map = self.extern_crate_map; let reexport_map = self.reexport_map; let maybe_unused_trait_imports = self.maybe_unused_trait_imports; @@ -1436,6 +1438,7 @@ impl<'a> Resolver<'a> { definitions, cstore: Box::new(self.crate_loader.into_cstore()), visibilities, + has_pub_restricted, access_levels, extern_crate_map, reexport_map, @@ -1462,6 +1465,7 @@ impl<'a> Resolver<'a> { access_levels: self.access_levels.clone(), cstore: Box::new(self.cstore().clone()), visibilities: self.visibilities.clone(), + has_pub_restricted: self.has_pub_restricted, extern_crate_map: self.extern_crate_map.clone(), reexport_map: self.reexport_map.clone(), glob_map: self.glob_map.clone(), diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 22d0a20395e..6681ea9d299 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -25,7 +25,6 @@ use rustc_middle::hir::nested_filter; use rustc_middle::span_bug; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::config::Input; -use rustc_span::source_map::respan; use rustc_span::symbol::Ident; use rustc_span::*; @@ -57,20 +56,14 @@ macro_rules! down_cast_data { } macro_rules! access_from { - ($save_ctxt:expr, $item:expr, $id:expr) => { + ($save_ctxt:expr, $id:expr) => { Access { - public: $item.vis.node.is_pub(), + public: $save_ctxt.tcx.visibility($id).is_public(), reachable: $save_ctxt.access_levels.is_reachable($id), } }; } -macro_rules! access_from_vis { - ($save_ctxt:expr, $vis:expr, $id:expr) => { - Access { public: $vis.node.is_pub(), reachable: $save_ctxt.access_levels.is_reachable($id) } - }; -} - pub struct DumpVisitor<'tcx> { pub save_ctxt: SaveContext<'tcx>, tcx: TyCtxt<'tcx>, @@ -257,7 +250,6 @@ impl<'tcx> DumpVisitor<'tcx> { def_id: LocalDefId, ident: Ident, generics: &'tcx hir::Generics<'tcx>, - vis: &hir::Visibility<'tcx>, span: Span, ) { debug!("process_method: {:?}:{}", def_id, ident); @@ -272,10 +264,10 @@ impl<'tcx> DumpVisitor<'tcx> { v.process_generic_params(&generics, &method_data.qualname, hir_id); method_data.value = - fn_to_string(sig.decl, sig.header, Some(ident.name), generics, vis, &[], None); + fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None); method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt); - v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, def_id), method_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, def_id), method_data); } // walk arg and return types @@ -302,7 +294,7 @@ impl<'tcx> DumpVisitor<'tcx> { let field_data = self.save_ctxt.get_field_data(field, parent_id); if let Some(field_data) = field_data { self.dumper.dump_def( - &access_from!(self.save_ctxt, field, self.tcx.hir().local_def_id(field.hir_id)), + &access_from!(self.save_ctxt, self.tcx.hir().local_def_id(field.hir_id)), field_data, ); } @@ -369,7 +361,7 @@ impl<'tcx> DumpVisitor<'tcx> { v.process_formals(body.params, &fn_data.qualname); v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id()); - v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), fn_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), fn_data); } for arg in decl.inputs { @@ -393,7 +385,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.nest_typeck_results(item.def_id, |v| { if let Some(var_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(var_data, DefData, item.span); - v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), var_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), var_data); } v.visit_ty(&typ); v.visit_expr(expr); @@ -407,7 +399,6 @@ impl<'tcx> DumpVisitor<'tcx> { typ: &'tcx hir::Ty<'tcx>, expr: Option<&'tcx hir::Expr<'tcx>>, parent_id: DefId, - vis: &hir::Visibility<'tcx>, attrs: &'tcx [ast::Attribute], ) { let qualname = format!("::{}", self.tcx.def_path_str(def_id.to_def_id())); @@ -418,7 +409,7 @@ impl<'tcx> DumpVisitor<'tcx> { let span = self.span_from_span(ident.span); self.dumper.dump_def( - &access_from_vis!(self.save_ctxt, vis, def_id), + &access_from!(self.save_ctxt, def_id), Def { kind: DefKind::Const, id: id_from_hir_id(hir_id, &self.save_ctxt), @@ -469,7 +460,11 @@ impl<'tcx> DumpVisitor<'tcx> { let fields_str = fields .iter() .filter_map(|f| { - if include_priv_fields || f.vis.node.is_pub() { + if include_priv_fields { + return Some(f.ident.to_string()); + } + let def_id = self.save_ctxt.tcx.hir().local_def_id(f.hir_id); + if self.save_ctxt.tcx.visibility(def_id).is_public() { Some(f.ident.to_string()) } else { None @@ -487,7 +482,7 @@ impl<'tcx> DumpVisitor<'tcx> { let span = self.span_from_span(item.ident.span); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item, item.def_id), + &access_from!(self.save_ctxt, item.def_id), Def { kind, id: id_from_def_id(item.def_id.to_def_id()), @@ -527,7 +522,7 @@ impl<'tcx> DumpVisitor<'tcx> { }; down_cast_data!(enum_data, DefData, item.span); - let access = access_from!(self.save_ctxt, item, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id); for variant in enum_definition.variants { let name = variant.ident.name.to_string(); @@ -662,7 +657,7 @@ impl<'tcx> DumpVisitor<'tcx> { methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item, item.def_id), + &access_from!(self.save_ctxt, item.def_id), Def { kind: DefKind::Trait, id, @@ -724,7 +719,7 @@ impl<'tcx> DumpVisitor<'tcx> { fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(mod_data, DefData, item.span); - self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.def_id), mod_data); + self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id), mod_data); } } @@ -979,11 +974,9 @@ impl<'tcx> DumpVisitor<'tcx> { fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) { self.process_macro_use(trait_item.span); - let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { hir::TraitItemKind::Const(ref ty, body) => { let body = body.map(|b| &self.tcx.hir().body(b).value); - let respan = respan(vis_span, hir::VisibilityKind::Public); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.process_assoc_const( trait_item.def_id, @@ -991,21 +984,18 @@ impl<'tcx> DumpVisitor<'tcx> { &ty, body, trait_id, - &respan, attrs, ); } hir::TraitItemKind::Fn(ref sig, ref trait_fn) => { let body = if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None }; - let respan = respan(vis_span, hir::VisibilityKind::Public); self.process_method( sig, body, trait_item.def_id, trait_item.ident, &trait_item.generics, - &respan, trait_item.span, ); } @@ -1064,7 +1054,6 @@ impl<'tcx> DumpVisitor<'tcx> { &ty, Some(&body.value), impl_id, - &impl_item.vis, attrs, ); } @@ -1075,7 +1064,6 @@ impl<'tcx> DumpVisitor<'tcx> { impl_item.def_id, impl_item.ident, &impl_item.generics, - &impl_item.vis, impl_item.span, ); } @@ -1147,7 +1135,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { hir::ItemKind::Use(path, hir::UseKind::Single) => { let sub_span = path.segments.last().unwrap().ident.span; if !self.span.filter_generated(sub_span) { - let access = access_from!(self.save_ctxt, item, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id); let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id); let span = self.span_from_span(sub_span); let parent = @@ -1176,7 +1164,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { // we don't want to track anyway, since it's probably macro-internal `use` if let Some(sub_span) = self.span.sub_span_of_star(item.span) { if !self.span.filter_generated(item.span) { - let access = access_from!(self.save_ctxt, item, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id); let span = self.span_from_span(sub_span); let parent = self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id); @@ -1249,7 +1237,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item, item.def_id), + &access_from!(self.save_ctxt, item.def_id), Def { kind: DefKind::Type, id, @@ -1443,7 +1431,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - let access = access_from!(self.save_ctxt, item, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id); match item.kind { hir::ForeignItemKind::Fn(decl, _, ref generics) => { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 102268c6ca3..582186cbd1f 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -27,7 +27,6 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, Input, OutputType}; use rustc_session::cstore::ExternCrate; use rustc_session::output::{filename_for_metadata, out_filename}; -use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::*; @@ -165,7 +164,6 @@ impl<'tcx> SaveContext<'tcx> { }, Some(item.ident.name), generics, - &item.vis, arg_names, None, ), @@ -221,7 +219,6 @@ impl<'tcx> SaveContext<'tcx> { sig.header, Some(item.ident.name), generics, - &item.vis, &[], None, ), @@ -310,7 +307,7 @@ impl<'tcx> SaveContext<'tcx> { let qualname = format!("::{}", self.tcx.def_path_str(def_id)); filter!(self.span_utils, item.ident.span); let value = - enum_def_to_string(def, generics, item.ident.name, item.span, &item.vis); + enum_def_to_string(def, generics, item.ident.name, item.span); Some(Data::DefData(Def { kind: DefKind::Enum, id: id_from_def_id(def_id), @@ -595,11 +592,6 @@ impl<'tcx> SaveContext<'tcx> { Node::TraitRef(tr) => tr.path.res, Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res, - Node::Visibility(&Spanned { - node: hir::VisibilityKind::Restricted { ref path, .. }, - .. - }) => path.res, - Node::PathSegment(seg) => match seg.res { Some(res) if res != Res::Err => res, _ => { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5a447aa6237..925f6bfd93d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3,20 +3,18 @@ pub use crate::options::*; -use crate::lint; use crate::search_paths::SearchPath; use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; use crate::{early_error, early_warn, Session}; +use crate::{lint, HashStableContext}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::impl_stable_hash_via_hash; +use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_target::abi::{Align, TargetDataLayout}; use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings}; use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS}; -use rustc_serialize::json; - use crate::parse::{CrateCheckConfig, CrateConfig}; use rustc_feature::UnstableFeatures; use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; @@ -80,7 +78,7 @@ pub enum CFProtection { Full, } -#[derive(Clone, Copy, Debug, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)] pub enum OptLevel { No, // -O0 Less, // -O1 @@ -90,8 +88,6 @@ pub enum OptLevel { SizeMin, // -Oz } -impl_stable_hash_via_hash!(OptLevel); - /// This is what the `LtoCli` values get mapped to after resolving defaults and /// and taking other command line options into account. /// @@ -232,15 +228,13 @@ impl SwitchWithOptPath { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic)] #[derive(Encodable, Decodable)] pub enum SymbolManglingVersion { Legacy, V0, } -impl_stable_hash_via_hash!(SymbolManglingVersion); - #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum DebugInfo { None, @@ -279,7 +273,7 @@ impl FromStr for SplitDwarfKind { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)] #[derive(Encodable, Decodable)] pub enum OutputType { Bitcode, @@ -292,7 +286,13 @@ pub enum OutputType { DepInfo, } -impl_stable_hash_via_hash!(OutputType); +impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType { + type KeyType = Self; + + fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { + *self + } +} impl OutputType { fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { @@ -398,7 +398,7 @@ pub enum TrimmedDefPaths { /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break /// dependency tracking for command-line arguments. Also only hash keys, since tracking /// should only depend on the output types, not the paths they're written to. -#[derive(Clone, Debug, Hash)] +#[derive(Clone, Debug, Hash, HashStable_Generic)] pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>); impl OutputTypes { @@ -460,9 +460,6 @@ impl OutputTypes { #[derive(Clone)] pub struct Externs(BTreeMap<String, ExternEntry>); -#[derive(Clone)] -pub struct ExternDepSpecs(BTreeMap<String, ExternDepSpec>); - #[derive(Clone, Debug)] pub struct ExternEntry { pub location: ExternLocation, @@ -477,6 +474,11 @@ pub struct ExternEntry { /// This can be disabled with the `noprelude` option like /// `--extern noprelude:name`. pub add_prelude: bool, + /// The extern entry shouldn't be considered for unused dependency warnings. + /// + /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to + /// suppress `unused-crate-dependencies` warnings. + pub nounused_dep: bool, } #[derive(Clone, Debug)] @@ -494,27 +496,6 @@ pub enum ExternLocation { ExactPaths(BTreeSet<CanonicalizedPath>), } -/// Supplied source location of a dependency - for example in a build specification -/// file like Cargo.toml. We support several syntaxes: if it makes sense to reference -/// a file and line, then the build system can specify that. On the other hand, it may -/// make more sense to have an arbitrary raw string. -#[derive(Clone, PartialEq)] -pub enum ExternDepSpec { - /// Raw string - Raw(String), - /// Raw data in json format - Json(json::Json), -} - -impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec { - fn from(from: &'a ExternDepSpec) -> Self { - match from { - ExternDepSpec::Raw(s) => rustc_lint_defs::ExternDepSpec::Raw(s.clone()), - ExternDepSpec::Json(json) => rustc_lint_defs::ExternDepSpec::Json(json.clone()), - } - } -} - impl Externs { /// Used for testing. pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs { @@ -536,7 +517,7 @@ impl Externs { impl ExternEntry { fn new(location: ExternLocation) -> ExternEntry { - ExternEntry { location, is_private_dep: false, add_prelude: false } + ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false } } pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> { @@ -547,25 +528,6 @@ impl ExternEntry { } } -impl ExternDepSpecs { - pub fn new(data: BTreeMap<String, ExternDepSpec>) -> ExternDepSpecs { - ExternDepSpecs(data) - } - - pub fn get(&self, key: &str) -> Option<&ExternDepSpec> { - self.0.get(key) - } -} - -impl fmt::Display for ExternDepSpec { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ExternDepSpec::Raw(raw) => fmt.write_str(raw), - ExternDepSpec::Json(json) => json::as_json(json).fmt(fmt), - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PrintRequest { FileNames, @@ -630,7 +592,7 @@ impl Input { } } -#[derive(Clone, Hash, Debug)] +#[derive(Clone, Hash, Debug, HashStable_Generic)] pub struct OutputFilenames { pub out_directory: PathBuf, filestem: String, @@ -639,8 +601,6 @@ pub struct OutputFilenames { pub outputs: OutputTypes, } -impl_stable_hash_via_hash!(OutputFilenames); - pub const RLINK_EXT: &str = "rlink"; pub const RUST_CGU_EXT: &str = "rcgu"; pub const DWARF_OBJECT_EXT: &str = "dwo"; @@ -785,7 +745,6 @@ impl Default for Options { cg: Default::default(), error_format: ErrorOutputType::default(), externs: Externs(BTreeMap::new()), - extern_dep_specs: ExternDepSpecs(BTreeMap::new()), crate_name: None, libs: Vec::new(), unstable_features: UnstableFeatures::Disallow, @@ -854,15 +813,14 @@ impl DebuggingOptions { } // The type of entry function, so users can have their own entry functions -#[derive(Copy, Clone, PartialEq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)] pub enum EntryFnType { Main, Start, } -impl_stable_hash_via_hash!(EntryFnType); - #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] +#[derive(HashStable_Generic)] pub enum CrateType { Executable, Dylib, @@ -872,8 +830,6 @@ pub enum CrateType { ProcMacro, } -impl_stable_hash_via_hash!(CrateType); - impl CrateType { /// When generated, is this crate type an archive? pub fn is_archive(&self) -> bool { @@ -1454,12 +1410,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> { "Specify where an external rust library is located", "NAME[=PATH]", ), - opt::multi_s( - "", - "extern-location", - "Location where an external crate dependency is specified", - "NAME=LOCATION", - ), opt::opt_s("", "sysroot", "Override the system root", "PATH"), opt::multi("Z", "", "Set internal debugging options", "FLAG"), opt::opt_s( @@ -2186,6 +2136,7 @@ pub fn parse_externs( let mut is_private_dep = false; let mut add_prelude = true; + let mut nounused_dep = false; if let Some(opts) = options { if !is_unstable_enabled { early_error( @@ -2207,6 +2158,7 @@ pub fn parse_externs( ); } } + "nounused" => nounused_dep = true, _ => early_error(error_format, &format!("unknown --extern option `{opt}`")), } } @@ -2215,74 +2167,14 @@ pub fn parse_externs( // Crates start out being not private, and go to being private `priv` // is specified. entry.is_private_dep |= is_private_dep; + // likewise `nounused` + entry.nounused_dep |= nounused_dep; // If any flag is missing `noprelude`, then add to the prelude. entry.add_prelude |= add_prelude; } Externs(externs) } -fn parse_extern_dep_specs( - matches: &getopts::Matches, - debugging_opts: &DebuggingOptions, - error_format: ErrorOutputType, -) -> ExternDepSpecs { - let is_unstable_enabled = debugging_opts.unstable_options; - let mut map = BTreeMap::new(); - - for arg in matches.opt_strs("extern-location") { - if !is_unstable_enabled { - early_error( - error_format, - "`--extern-location` option is unstable: set `-Z unstable-options`", - ); - } - - let mut parts = arg.splitn(2, '='); - let name = parts.next().unwrap_or_else(|| { - early_error(error_format, "`--extern-location` value must not be empty") - }); - let loc = parts.next().unwrap_or_else(|| { - early_error( - error_format, - &format!("`--extern-location`: specify location for extern crate `{name}`"), - ) - }); - - let locparts: Vec<_> = loc.split(':').collect(); - let spec = match &locparts[..] { - ["raw", ..] => { - // Don't want `:` split string - let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| { - early_error(error_format, "`--extern-location`: missing `raw` location") - }); - ExternDepSpec::Raw(raw.to_string()) - } - ["json", ..] => { - // Don't want `:` split string - let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| { - early_error(error_format, "`--extern-location`: missing `json` location") - }); - let json = json::from_str(raw).unwrap_or_else(|_| { - early_error( - error_format, - &format!("`--extern-location`: malformed json location `{raw}`"), - ) - }); - ExternDepSpec::Json(json) - } - [bad, ..] => early_error( - error_format, - &format!("unknown location type `{bad}`: use `raw` or `json`"), - ), - [] => early_error(error_format, "missing location specification"), - }; - - map.insert(name.to_string(), spec); - } - - ExternDepSpecs::new(map) -} - fn parse_remap_path_prefix( matches: &getopts::Matches, debugging_opts: &DebuggingOptions, @@ -2525,7 +2417,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } let externs = parse_externs(matches, &debugging_opts, error_format); - let extern_dep_specs = parse_extern_dep_specs(matches, &debugging_opts, error_format); let crate_name = matches.opt_str("crate-name"); @@ -2601,7 +2492,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { error_format, externs, unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), - extern_dep_specs, crate_name, libs, debug_assertions, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4994f8eaeb2..96f50e57ac4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -183,7 +183,6 @@ top_level_options!( borrowck_mode: BorrowckMode [UNTRACKED], cg: CodegenOptions [SUBSTRUCT], externs: Externs [UNTRACKED], - extern_dep_specs: ExternDepSpecs [UNTRACKED], crate_name: Option<String> [TRACKED], /// Indicates how the compiler should treat unstable features. unstable_features: UnstableFeatures [TRACKED], @@ -369,6 +368,8 @@ mod desc { pub const parse_opt_langid: &str = "a language identifier"; pub const parse_opt_pathbuf: &str = "a path"; pub const parse_list: &str = "a space-separated list of strings"; + pub const parse_list_with_polarity: &str = + "a comma-separated list of strings, with elements beginning with + or -"; pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; @@ -530,6 +531,19 @@ mod parse { } } + crate fn parse_list_with_polarity(slot: &mut Vec<(String, bool)>, v: Option<&str>) -> bool { + match v { + Some(s) => { + for s in s.split(",") { + let Some(pass_name) = s.strip_prefix(&['+', '-'][..]) else { return false }; + slot.push((pass_name.to_string(), &s[..1] == "+")); + } + true + } + None => false, + } + } + crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool { if let Some(v) = v { ld.line = false; @@ -1319,6 +1333,10 @@ options! { mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), + mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED], + "use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \ + enabled, overriding all other checks. Passes that are not specified are enabled or \ + disabled by other flags as usual."), mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED], diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index b6bde28233d..56a6b6f3b03 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -26,7 +26,7 @@ pub struct SearchPathFile { pub file_name_str: String, } -#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)] +#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable, HashStable_Generic)] pub enum PathKind { Native, Crate, @@ -36,8 +36,6 @@ pub enum PathKind { All, } -rustc_data_structures::impl_stable_hash_via_hash!(PathKind); - impl PathKind { pub fn matches(&self, kind: PathKind) -> bool { match (self, kind) { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 9a286d94ab8..8064c217457 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -18,6 +18,7 @@ impl Session { } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(HashStable_Generic)] pub enum NativeLibKind { /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) Static { @@ -57,9 +58,8 @@ impl NativeLibKind { } } -rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind); - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(HashStable_Generic)] pub struct NativeLib { pub name: String, pub new_name: Option<String>, @@ -73,8 +73,6 @@ impl NativeLib { } } -rustc_data_structures::impl_stable_hash_via_hash!(NativeLib); - /// A path that has been canonicalized along with its original, non-canonicalized form #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct CanonicalizedPath { diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 6d1b36796d8..d5f806308cf 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -283,8 +283,19 @@ impl DefId { self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self)) } + #[inline] + pub fn is_crate_root(self) -> bool { + self.index == CRATE_DEF_INDEX + } + + #[inline] + pub fn as_crate_root(self) -> Option<CrateNum> { + if self.is_crate_root() { Some(self.krate) } else { None } + } + + #[inline] pub fn is_top_level_module(self) -> bool { - self.is_local() && self.index == CRATE_DEF_INDEX + self.is_local() && self.is_crate_root() } } @@ -357,7 +368,7 @@ impl LocalDefId { #[inline] pub fn is_top_level_module(self) -> bool { - self.local_def_index == CRATE_DEF_INDEX + self == CRATE_DEF_ID } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b132c0a2132..f22faef2580 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -59,6 +59,8 @@ pub use symbol::{sym, Symbol}; mod analyze_source_file; pub mod fatal_error; +pub mod profiling; + use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; @@ -1130,6 +1132,7 @@ impl ExternalSource { pub struct OffsetOverflowError; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(HashStable_Generic)] pub enum SourceFileHashAlgorithm { Md5, Sha1, @@ -1149,8 +1152,6 @@ impl FromStr for SourceFileHashAlgorithm { } } -rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm); - /// The hash of the on-disk source file used for debug info. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(HashStable_Generic, Encodable, Decodable)] diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs new file mode 100644 index 00000000000..f169007fab4 --- /dev/null +++ b/compiler/rustc_span/src/profiling.rs @@ -0,0 +1,35 @@ +use std::borrow::Borrow; + +use rustc_data_structures::profiling::EventArgRecorder; + +/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's +/// event arguments. +pub trait SpannedEventArgRecorder { + /// Records the following event arguments within the current generic activity being profiled: + /// - the provided `event_arg` + /// - a string representation of the provided `span` + /// + /// Note: when self-profiling with costly event arguments, at least one argument + /// needs to be recorded. A panic will be triggered if that doesn't happen. + fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span) + where + A: Borrow<str> + Into<String>; +} + +impl SpannedEventArgRecorder for EventArgRecorder<'_> { + fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span) + where + A: Borrow<str> + Into<String>, + { + self.record_arg(event_arg); + + let span_arg = crate::with_session_globals(|session_globals| { + if let Some(source_map) = &*session_globals.source_map.borrow() { + source_map.span_to_embeddable_string(span) + } else { + format!("{:?}", span) + } + }); + self.record_arg(span_arg); + } +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d9bada29589..e3ce8105a8b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -803,6 +803,7 @@ symbols! { keyword, kind, kreg, + kreg0, label, label_break_value, lang, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 5bc4b566daf..6bc807c7c44 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -893,7 +893,7 @@ impl InlineAsmClobberAbi { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - k1, k2, k3, k4, k5, k6, k7, + k0, k1, k2, k3, k4, k5, k6, k7, mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, st0, st1, st2, st3, st4, st5, st6, st7, @@ -908,7 +908,7 @@ impl InlineAsmClobberAbi { zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31, - k1, k2, k3, k4, k5, k6, k7, + k0, k1, k2, k3, k4, k5, k6, k7, mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, st0, st1, st2, st3, st4, st5, st6, st7, @@ -927,7 +927,7 @@ impl InlineAsmClobberAbi { zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31, - k1, k2, k3, k4, k5, k6, k7, + k0, k1, k2, k3, k4, k5, k6, k7, mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, st0, st1, st2, st3, st4, st5, st6, st7, diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 7c136a47548..854674c7f2f 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -14,6 +14,7 @@ def_reg_class! { ymm_reg, zmm_reg, kreg, + kreg0, mmx_reg, x87_reg, } @@ -38,7 +39,7 @@ impl X86InlineAsmRegClass { } Self::reg_byte => &[], Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'], - Self::kreg => &[], + Self::kreg | Self::kreg0 => &[], Self::mmx_reg | Self::x87_reg => &[], } } @@ -77,7 +78,7 @@ impl X86InlineAsmRegClass { 256 => Some(('y', "ymm0")), _ => Some(('x', "xmm0")), }, - Self::kreg => None, + Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, } } @@ -95,7 +96,7 @@ impl X86InlineAsmRegClass { Self::xmm_reg => Some(('x', "xmm0")), Self::ymm_reg => Some(('y', "ymm0")), Self::zmm_reg => Some(('z', "zmm0")), - Self::kreg => None, + Self::kreg | Self::kreg0 => None, Self::mmx_reg | Self::x87_reg => None, } } @@ -132,6 +133,7 @@ impl X86InlineAsmRegClass { avx512f: I8, I16; avx512bw: I32, I64; }, + Self::kreg0 => &[], Self::mmx_reg | Self::x87_reg => &[], } } @@ -294,6 +296,7 @@ def_regs! { zmm29: zmm_reg = ["zmm29", "xmm29", "ymm29"] % x86_64_only, zmm30: zmm_reg = ["zmm30", "xmm30", "ymm30"] % x86_64_only, zmm31: zmm_reg = ["zmm31", "xmm31", "ymm31"] % x86_64_only, + k0: kreg0 = ["k0"], k1: kreg = ["k1"], k2: kreg = ["k2"], k3: kreg = ["k3"], @@ -323,8 +326,6 @@ def_regs! { "the stack pointer cannot be used as an operand for inline asm", #error = ["ip", "eip", "rip"] => "the instruction pointer cannot be used as an operand for inline asm", - #error = ["k0"] => - "the k0 AVX mask register cannot be used as an operand for inline asm", } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7485c082f4e..0c1ca65c48f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -19,9 +19,11 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; +use rustc_middle::hir::map; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, - Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, + GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, ToPredicate, Ty, TyCtxt, + TypeFoldable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; @@ -44,6 +46,123 @@ pub enum GeneratorInteriorOrUpvar { Upvar(Span), } +// This type provides a uniform interface to retrieve data on generators, whether it originated from +// the local crate being compiled or from a foreign crate. +#[derive(Debug)] +pub enum GeneratorData<'tcx, 'a> { + Local(&'a TypeckResults<'tcx>), + Foreign(&'tcx GeneratorDiagnosticData<'tcx>), +} + +impl<'tcx, 'a> GeneratorData<'tcx, 'a> { + // Try to get information about variables captured by the generator that matches a type we are + // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to + // meet an obligation + fn try_get_upvar_span<F>( + &self, + infer_context: &InferCtxt<'a, 'tcx>, + generator_did: DefId, + ty_matches: F, + ) -> Option<GeneratorInteriorOrUpvar> + where + F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool, + { + match self { + GeneratorData::Local(typeck_results) => { + infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| { + upvars.iter().find_map(|(upvar_id, upvar)| { + let upvar_ty = typeck_results.node_type(*upvar_id); + let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty); + if ty_matches(ty::Binder::dummy(upvar_ty)) { + Some(GeneratorInteriorOrUpvar::Upvar(upvar.span)) + } else { + None + } + }) + }) + } + GeneratorData::Foreign(_) => None, + } + } + + // Try to get the span of a type being awaited on that matches the type we are looking with the + // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an + // obligation + fn get_from_await_ty<F>( + &self, + visitor: AwaitsVisitor, + hir: map::Map<'tcx>, + ty_matches: F, + ) -> Option<Span> + where + F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool, + { + match self { + GeneratorData::Local(typeck_results) => visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| { + ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr))) + }) + .map(|expr| expr.span), + GeneratorData::Foreign(generator_diagnostic_data) => visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| { + ty_matches(ty::Binder::dummy( + generator_diagnostic_data + .adjustments + .get(&await_expr.hir_id.local_id) + .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..]) + .last() + .map_or_else::<Ty<'tcx>, _, _>( + || { + generator_diagnostic_data + .nodes_types + .get(&await_expr.hir_id.local_id) + .cloned() + .unwrap_or_else(|| { + bug!( + "node_type: no type for node `{}`", + ty::tls::with(|tcx| tcx + .hir() + .node_to_string(await_expr.hir_id)) + ) + }) + }, + |adj| adj.target, + ), + )) + }) + .map(|expr| expr.span), + } + } + + /// Get the type, expression, span and optional scope span of all types + /// that are live across the yield of this generator + fn get_generator_interior_types( + &self, + ) -> ty::Binder<'tcx, &Vec<GeneratorInteriorTypeCause<'tcx>>> { + match self { + GeneratorData::Local(typeck_result) => typeck_result.generator_interior_types.as_ref(), + GeneratorData::Foreign(generator_diagnostic_data) => { + generator_diagnostic_data.generator_interior_types.as_ref() + } + } + } + + // Used to get the source of the data, note we don't have as much information for generators + // originated from foreign crates + fn is_foreign(&self) -> bool { + match self { + GeneratorData::Local(_) => false, + GeneratorData::Foreign(_) => true, + } + } +} + // This trait is public to expose the diagnostics methods to clippy. pub trait InferCtxtExt<'tcx> { fn suggest_restricting_param_bound( @@ -152,7 +271,7 @@ pub trait InferCtxtExt<'tcx> { err: &mut Diagnostic, interior_or_upvar_span: GeneratorInteriorOrUpvar, interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>, - inner_generator_body: Option<&hir::Body<'tcx>>, + is_async: bool, outer_generator: Option<DefId>, trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, @@ -1642,6 +1761,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .map(|def_id| hir.local_def_id_to_hir_id(def_id)) .and_then(|hir_id| hir.maybe_body_owned_by(hir_id)) .map(|body_id| hir.body(body_id)); + let is_async = match generator_did.as_local() { + Some(_) => generator_body + .and_then(|body| body.generator_kind()) + .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..))) + .unwrap_or(false), + None => self + .tcx + .generator_kind(generator_did) + .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..))) + .unwrap_or(false), + }; let mut visitor = AwaitsVisitor::default(); if let Some(body) = generator_body { visitor.visit_body(body); @@ -1682,61 +1812,55 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // type-checking; otherwise, get them by performing a query. This is needed to avoid // cycles. If we can't use resolved types because the generator comes from another crate, // we still provide a targeted error but without all the relevant spans. - let query_typeck_results; - let typeck_results: Option<&TypeckResults<'tcx>> = match &in_progress_typeck_results { - Some(t) if t.hir_owner.to_def_id() == generator_did_root => Some(&t), + let generator_data: Option<GeneratorData<'tcx, '_>> = match &in_progress_typeck_results { + Some(t) if t.hir_owner.to_def_id() == generator_did_root => { + Some(GeneratorData::Local(&t)) + } _ if generator_did.is_local() => { - query_typeck_results = self.tcx.typeck(generator_did.expect_local()); - Some(&query_typeck_results) + Some(GeneratorData::Local(self.tcx.typeck(generator_did.expect_local()))) } - _ => None, // Do not ICE on closure typeck (#66868). + _ => self + .tcx + .generator_diagnostic_data(generator_did) + .as_ref() + .map(|generator_diag_data| GeneratorData::Foreign(generator_diag_data)), }; - if let Some(typeck_results) = typeck_results { - if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) { - interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| { - let upvar_ty = typeck_results.node_type(*upvar_id); - let upvar_ty = self.resolve_vars_if_possible(upvar_ty); - if ty_matches(ty::Binder::dummy(upvar_ty)) { - Some(GeneratorInteriorOrUpvar::Upvar(upvar.span)) - } else { - None - } - }); - }; + + if let Some(generator_data) = generator_data.as_ref() { + interior_or_upvar_span = + generator_data.try_get_upvar_span(&self, generator_did, ty_matches); // The generator interior types share the same binders if let Some(cause) = - typeck_results.generator_interior_types.as_ref().skip_binder().iter().find( + generator_data.get_generator_interior_types().skip_binder().iter().find( |ty::GeneratorInteriorTypeCause { ty, .. }| { - ty_matches(typeck_results.generator_interior_types.rebind(*ty)) + ty_matches(generator_data.get_generator_interior_types().rebind(*ty)) }, ) { - // Check to see if any awaited expressions have the target type. - let from_awaited_ty = visitor - .awaits - .into_iter() - .map(|id| hir.expect_expr(id)) - .find(|await_expr| { - ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr))) - }) - .map(|expr| expr.span); + let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches); let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause; interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span)); interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty)); - }; - } else { - interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span)); + } + + if interior_or_upvar_span.is_none() && generator_data.is_foreign() { + interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span)); + } } if let Some(interior_or_upvar_span) = interior_or_upvar_span { + let typeck_results = generator_data.and_then(|generator_data| match generator_data { + GeneratorData::Local(typeck_results) => Some(typeck_results), + GeneratorData::Foreign(_) => None, + }); self.note_obligation_cause_for_async_await( err, interior_or_upvar_span, interior_extra_info, - generator_body, + is_async, outer_generator, trait_ref, target_ty, @@ -1757,7 +1881,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut Diagnostic, interior_or_upvar_span: GeneratorInteriorOrUpvar, interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>, - inner_generator_body: Option<&hir::Body<'tcx>>, + is_async: bool, outer_generator: Option<DefId>, trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, @@ -1767,10 +1891,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { let source_map = self.tcx.sess.source_map(); - let is_async = inner_generator_body - .and_then(|body| body.generator_kind()) - .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..))) - .unwrap_or(false); let (await_or_yield, an_await_or_yield) = if is_async { ("await", "an await") } else { ("yield", "a yield") }; let future_or_generator = if is_async { "future" } else { "generator" }; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 6bae0f2eac9..1cd0ace8adb 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2563,40 +2563,77 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We proactively collect all the inferred type params to emit a single error per fn def. let mut visitor = HirPlaceholderCollector::default(); - for ty in decl.inputs { - visitor.visit_ty(ty); - } + let mut infer_replacements = vec![]; + walk_generics(&mut visitor, generics); - let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); + let input_tys: Vec<_> = decl + .inputs + .iter() + .enumerate() + .map(|(i, a)| { + if let hir::TyKind::Infer = a.kind && !self.allow_ty_infer() { + if let Some(suggested_ty) = + self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) + { + infer_replacements.push((a.span, suggested_ty.to_string())); + return suggested_ty; + } + } + + // Only visit the type looking for `_` if we didn't fix the type above + visitor.visit_ty(a); + self.ty_of_arg(a, None) + }) + .collect(); + let output_ty = match decl.output { hir::FnRetTy::Return(output) => { - visitor.visit_ty(output); - self.ast_ty_to_ty(output) + if let hir::TyKind::Infer = output.kind + && !self.allow_ty_infer() + && let Some(suggested_ty) = + self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) + { + infer_replacements.push((output.span, suggested_ty.to_string())); + suggested_ty + } else { + visitor.visit_ty(output); + self.ast_ty_to_ty(output) + } } hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), }; debug!("ty_of_fn: output_ty={:?}", output_ty); - let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); + let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); - if !self.allow_ty_infer() { + if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) { // We always collect the spans for placeholder types when evaluating `fn`s, but we // only want to emit an error complaining about them if infer types (`_`) are not // allowed. `allow_ty_infer` gates this behavior. We check for the presence of // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. - crate::collect::placeholder_type_error( + let mut diag = crate::collect::placeholder_type_error_diag( tcx, ident_span.map(|sp| sp.shrink_to_hi()), generics.params, visitor.0, + infer_replacements.iter().map(|(s, _)| *s).collect(), true, hir_ty, "function", ); + + if !infer_replacements.is_empty() { + diag.multipart_suggestion(&format!( + "try replacing `_` with the type{} in the corresponding trait method signature", + rustc_errors::pluralize!(infer_replacements.len()), + ), infer_replacements, Applicability::MachineApplicable); + } + + diag.emit(); } // Find any late-bound regions declared in return type that do @@ -2624,6 +2661,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bare_fn_ty } + /// Given a fn_hir_id for a impl function, suggest the type that is found on the + /// corresponding function in the trait that the impl implements, if it exists. + /// If arg_idx is Some, then it corresponds to an input type index, otherwise it + /// corresponds to the return type. + fn suggest_trait_fn_ty_for_impl_fn_infer( + &self, + fn_hir_id: hir::HirId, + arg_idx: Option<usize>, + ) -> Option<Ty<'tcx>> { + let tcx = self.tcx(); + let hir = tcx.hir(); + + let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) = + hir.get(fn_hir_id) else { return None }; + let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) = + hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; + + let trait_ref = + self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty)); + + let x: &ty::AssocItem = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( + tcx, + *ident, + ty::AssocKind::Fn, + trait_ref.def_id, + )?; + + let fn_sig = tcx.fn_sig(x.def_id).subst( + tcx, + trait_ref.substs.extend_to(tcx, x.def_id, |param, _| tcx.mk_param_from_def(param)), + ); + + let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() }; + + Some(tcx.erase_late_bound_regions(ty)) + } + fn validate_late_bound_regions( &self, constrained_regions: FxHashSet<ty::BoundRegionKind>, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 80f6190732a..616aa11f00a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -968,9 +968,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { SuggestionText::Remove(plural) => { Some(format!("remove the extra argument{}", if plural { "s" } else { "" })) } - SuggestionText::Swap => Some(format!("swap these arguments")), - SuggestionText::Reorder => Some(format!("reorder these arguments")), - SuggestionText::DidYouMean => Some(format!("did you mean")), + SuggestionText::Swap => Some("swap these arguments".to_string()), + SuggestionText::Reorder => Some("reorder these arguments".to_string()), + SuggestionText::DidYouMean => Some("did you mean".to_string()), }; if let Some(suggestion_text) = suggestion_text { let source_map = self.sess().source_map(); diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs index 75a8ad8a159..721f251650f 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs @@ -257,7 +257,6 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { | hir::Node::Ctor(..) | hir::Node::Lifetime(..) | hir::Node::GenericParam(..) - | hir::Node::Visibility(..) | hir::Node::Crate(..) | hir::Node::Infer(..) => bug!("Unsupported branch target: {:?}", node), } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index f3dcf5fff74..cf0c5703cd0 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -2042,63 +2042,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess, span, E0529, - "expected an array or slice, found `{}`", - expected_ty + "expected an array or slice, found `{expected_ty}`" ); - if let ty::Ref(_, ty, _) = expected_ty.kind() { - if let ty::Array(..) | ty::Slice(..) = ty.kind() { - err.help("the semantics of slice patterns changed recently; see issue #62254"); - } + if let ty::Ref(_, ty, _) = expected_ty.kind() + && let ty::Array(..) | ty::Slice(..) = ty.kind() + { + err.help("the semantics of slice patterns changed recently; see issue #62254"); } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) + && let (Some(span), true) = (ti.span, ti.origin_expr) + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - if let (Some(span), true) = (ti.span, ti.origin_expr) { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - let applicability = Autoderef::new( - &self.infcx, - self.param_env, - self.body_id, - span, - self.resolve_vars_if_possible(ti.expected), + let ty = self.resolve_vars_if_possible(ti.expected); + let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty); + match is_slice_or_array_or_vector.1.kind() { + ty::Adt(adt_def, _) + if self.tcx.is_diagnostic_item(sym::Option, adt_def.did()) + || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) => + { + // Slicing won't work here, but `.as_deref()` might (issue #91328). + err.span_suggestion( span, - ) - .find_map(|(ty, _)| { - match ty.kind() { - ty::Adt(adt_def, _) - if self.tcx.is_diagnostic_item(sym::Option, adt_def.did()) - || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) => - { - // Slicing won't work here, but `.as_deref()` might (issue #91328). - err.span_suggestion( - span, - "consider using `as_deref` here", - format!("{}.as_deref()", snippet), - Applicability::MaybeIncorrect, - ); - Some(None) - } - - ty::Slice(..) | ty::Array(..) => { - Some(Some(Applicability::MachineApplicable)) - } - - _ => None, - } - }) - .unwrap_or(Some(Applicability::MaybeIncorrect)); - - if let Some(applicability) = applicability { - err.span_suggestion( - span, - "consider slicing here", - format!("{}[..]", snippet), - applicability, - ); - } + "consider using `as_deref` here", + format!("{snippet}.as_deref()"), + Applicability::MaybeIncorrect, + ); } + _ => () + } + if is_slice_or_array_or_vector.0 { + err.span_suggestion( + span, + "consider slicing here", + format!("{snippet}[..]"), + Applicability::MachineApplicable, + ); } } - err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty)); + err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`")); err.emit(); } + + fn is_slice_or_array_or_vector( + &self, + err: &mut Diagnostic, + snippet: String, + ty: Ty<'tcx>, + ) -> (bool, Ty<'tcx>) { + match ty.kind() { + ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => { + (true, ty) + } + ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty), + ty::Slice(..) | ty::Array(..) => (true, ty), + _ => (false, ty), + } + } } diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index 4f792fa25a1..d52886a09bd 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -18,8 +18,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) { for id in tcx.hir().items() { if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) { + if tcx.visibility(id.def_id).is_public() { + continue; + } let item = tcx.hir().item(id); - if item.vis.node.is_pub() || item.span.is_dummy() { + if item.span.is_dummy() { continue; } if let hir::ItemKind::Use(path, _) = item.kind { @@ -176,7 +179,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), None => format!("use {};", item.ident.name), }; - let vis = tcx.sess.source_map().span_to_snippet(item.vis.span).unwrap_or_default(); + let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default(); let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) }; lint.build("`extern crate` is not idiomatic in the new edition") .span_suggestion_short( diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 77a53744829..19e68f0b14f 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -50,6 +50,7 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua tcx, sp, tr.path.span, + trait_ref.self_ty(), impl_.self_ty.span, &impl_.generics, err, @@ -201,18 +202,23 @@ fn emit_orphan_check_error<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, trait_span: Span, + self_ty: Ty<'tcx>, self_ty_span: Span, generics: &hir::Generics<'tcx>, err: traits::OrphanCheckErr<'tcx>, ) -> Result<!, ErrorGuaranteed> { Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { + let msg = match self_ty.kind() { + ty::Adt(..) => "can be implemented for types defined outside of the crate", + _ if self_ty.is_primitive() => "can be implemented for primitive types", + _ => "can be implemented for arbitrary types", + }; let mut err = struct_span_err!( tcx.sess, sp, E0117, - "only traits defined in the current crate can be implemented for \ - arbitrary types" + "only traits defined in the current crate {msg}" ); err.span_label(sp, "impl doesn't use only types from inside the current crate"); for (ty, is_target_ty) in &tys { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 153ab8d95fd..be77bdb0bf5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -160,6 +160,33 @@ crate fn placeholder_type_error<'tcx>( return; } + placeholder_type_error_diag( + tcx, + span, + generics, + placeholder_types, + vec![], + suggest, + hir_ty, + kind, + ) + .emit(); +} + +crate fn placeholder_type_error_diag<'tcx>( + tcx: TyCtxt<'tcx>, + span: Option<Span>, + generics: &[hir::GenericParam<'_>], + placeholder_types: Vec<Span>, + additional_spans: Vec<Span>, + suggest: bool, + hir_ty: Option<&hir::Ty<'_>>, + kind: &'static str, +) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + if placeholder_types.is_empty() { + return bad_placeholder(tcx, additional_spans, kind); + } + let type_name = generics.next_type_param_name(None); let mut sugg: Vec<_> = placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); @@ -182,7 +209,8 @@ crate fn placeholder_type_error<'tcx>( sugg.push((span, format!(", {}", type_name))); } - let mut err = bad_placeholder(tcx, placeholder_types, kind); + let mut err = + bad_placeholder(tcx, placeholder_types.into_iter().chain(additional_spans).collect(), kind); // Suggest, but only if it is not a function in const or static if suggest { @@ -218,7 +246,8 @@ crate fn placeholder_type_error<'tcx>( ); } } - err.emit(); + + err } fn reject_placeholder_type_signatures_in_item<'tcx>( @@ -1868,50 +1897,17 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { generics, .. }) - | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { - match get_infer_ret_ty(&sig.decl.output) { - Some(ty) => { - let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; - // Typeck doesn't expect erased regions to be returned from `type_of`. - let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r { - ty::ReErased => tcx.lifetimes.re_static, - _ => r, - }); - let fn_sig = ty::Binder::dummy(fn_sig); - - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_ty(ty); - let mut diag = bad_placeholder(tcx, visitor.0, "return type"); - let ret_ty = fn_sig.skip_binder().output(); - if !ret_ty.references_error() { - if !ret_ty.is_closure() { - let ret_ty_str = match ret_ty.kind() { - // Suggest a function pointer return type instead of a unique function definition - // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid - // syntax) - ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(), - _ => ret_ty.to_string(), - }; - diag.span_suggestion( - ty.span, - "replace with the correct return type", - ret_ty_str, - Applicability::MaybeIncorrect, - ); - } else { - // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds - // to prevent the user from getting a papercut while trying to use the unique closure - // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). - diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); - diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); - } - } - diag.emit(); + infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx) + } - fn_sig - } - None => <dyn AstConv<'_>>::ty_of_fn( + ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) => { + // Do not try to inference the return type for a impl method coming from a trait + if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = + tcx.hir().get(tcx.hir().get_parent_node(hir_id)) + && i.of_trait.is_some() + { + <dyn AstConv<'_>>::ty_of_fn( &icx, hir_id, sig.header.unsafety, @@ -1920,7 +1916,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { generics, Some(ident.span), None, - ), + ) + } else { + infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx) } } @@ -1982,6 +1980,70 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } } +fn infer_return_ty_for_fn_sig<'tcx>( + tcx: TyCtxt<'tcx>, + sig: &hir::FnSig<'_>, + ident: Ident, + generics: &hir::Generics<'_>, + def_id: LocalDefId, + icx: &ItemCtxt<'tcx>, +) -> ty::PolyFnSig<'tcx> { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + + match get_infer_ret_ty(&sig.decl.output) { + Some(ty) => { + let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; + // Typeck doesn't expect erased regions to be returned from `type_of`. + let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r { + ty::ReErased => tcx.lifetimes.re_static, + _ => r, + }); + let fn_sig = ty::Binder::dummy(fn_sig); + + let mut visitor = HirPlaceholderCollector::default(); + visitor.visit_ty(ty); + let mut diag = bad_placeholder(tcx, visitor.0, "return type"); + let ret_ty = fn_sig.skip_binder().output(); + if !ret_ty.references_error() { + if !ret_ty.is_closure() { + let ret_ty_str = match ret_ty.kind() { + // Suggest a function pointer return type instead of a unique function definition + // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid + // syntax) + ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(), + _ => ret_ty.to_string(), + }; + diag.span_suggestion( + ty.span, + "replace with the correct return type", + ret_ty_str, + Applicability::MaybeIncorrect, + ); + } else { + // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds + // to prevent the user from getting a papercut while trying to use the unique closure + // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). + diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); + diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); + } + } + diag.emit(); + + fn_sig + } + None => <dyn AstConv<'_>>::ty_of_fn( + icx, + hir_id, + sig.header.unsafety, + sig.header.abi, + sig.decl, + generics, + Some(ident.span), + None, + ), + } +} + fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { let icx = ItemCtxt::new(tcx, def_id); match tcx.hir().expect_item(def_id.expect_local()).kind { diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 1088be5f566..fc08171d2f4 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -134,7 +134,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> { #[primary_span] #[label] pub span: Span, - #[suggestion_verbose(message = "suggestion", code = "{ty}")] + #[suggestion_verbose(code = "{ty}")] pub opt_sugg: Option<(Span, Applicability)>, } |
