diff options
| author | bors <bors@rust-lang.org> | 2022-10-30 08:52:35 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-10-30 08:52:35 +0000 |
| commit | 962bf63dbfcb190bd752e2dbff7d133ab1101f5c (patch) | |
| tree | 0d0567de3defda59316b51e53e7687b36025df6f /compiler | |
| parent | c162fd36d250f1a76e00ffa55b9d827d0db7e0bc (diff) | |
| parent | 0b49a5d17354c3b0980c3148f8291e429fc9a194 (diff) | |
| download | rust-962bf63dbfcb190bd752e2dbff7d133ab1101f5c.tar.gz rust-962bf63dbfcb190bd752e2dbff7d133ab1101f5c.zip | |
Auto merge of #2639 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'compiler')
173 files changed, 2498 insertions, 1610 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7112c267577..4ef43735a62 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1112,24 +1112,6 @@ pub struct Expr { } impl Expr { - /// Returns `true` if this expression would be valid somewhere that expects a value; - /// for example, an `if` condition. - pub fn returns(&self) -> bool { - if let ExprKind::Block(ref block, _) = self.kind { - match block.stmts.last().map(|last_stmt| &last_stmt.kind) { - // Implicit return - Some(StmtKind::Expr(_)) => true, - // Last statement is an explicit return? - Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)), - // This is a block that doesn't end in either an implicit or explicit return. - _ => false, - } - } else { - // This is not a block, it is a value. - true - } - } - /// Is this expr either `N`, or `{ N }`. /// /// If this is not the case, name resolution does not resolve `N` when using diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 25022a02f4b..b970e57e017 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -152,6 +152,12 @@ pub trait MutVisitor: Sized { noop_visit_expr(e, self); } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) { + self.visit_expr(ex) + } + fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> { noop_filter_map_expr(e, self) } @@ -1301,7 +1307,7 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_ident(ident); vis.visit_id(id); visit_opt(args, |args| vis.visit_generic_args(args)); - vis.visit_expr(receiver); + vis.visit_method_receiver_expr(receiver); visit_exprs(exprs, vis); vis.visit_span(span); } @@ -1589,3 +1595,9 @@ impl DummyAstNode for Crate { } } } + +impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> { + fn dummy() -> Self { + crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy()) + } +} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e752cc7dc2d..6f56c1ef0e8 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized { fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } + /// This method is a hack to workaround unstable of `stmt_expr_attributes`. + /// It can be removed once that feature is stabilized. + fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) { + self.visit_expr(ex) + } fn visit_expr_post(&mut self, _ex: &'ast Expr) {} fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 6d716796343..f1851d7b40e 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - self.insert_nested(item.def_id.def_id); + self.insert_nested(item.owner_id.def_id); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - self.insert_nested(item_id.def_id.def_id); + self.insert_nested(item_id.owner_id.def_id); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.insert_nested(item_id.def_id.def_id); + self.insert_nested(item_id.owner_id.def_id); } fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { - self.insert_nested(foreign_id.def_id.def_id); + self.insert_nested(foreign_id.owner_id.def_id); } fn visit_nested_body(&mut self, id: BodyId) { @@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, i: &'hir Item<'hir>) { - debug_assert_eq!(i.def_id, self.owner); + debug_assert_eq!(i.owner_id, self.owner); self.with_parent(i.hir_id(), |this| { if let ItemKind::Struct(ref struct_def, _) = i.kind { // If this is a tuple or unit-like struct, register the constructor. @@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) { - debug_assert_eq!(fi.def_id, self.owner); + debug_assert_eq!(fi.owner_id, self.owner); self.with_parent(fi.hir_id(), |this| { intravisit::walk_foreign_item(this, fi); }); @@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { - debug_assert_eq!(ti.def_id, self.owner); + debug_assert_eq!(ti.owner_id, self.owner); self.with_parent(ti.hir_id(), |this| { intravisit::walk_trait_item(this, ti); }); @@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { - debug_assert_eq!(ii.def_id, self.owner); + debug_assert_eq!(ii.owner_id, self.owner); self.with_parent(ii.hir_id(), |this| { intravisit::walk_impl_item(this, ii); }); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2117006df10..76316a574ac 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { let mut node_ids = - smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; + smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; if let ItemKind::Use(ref use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } @@ -195,7 +195,7 @@ impl<'hir> LoweringContext<'_, 'hir> { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { vec.push(hir::ItemId { - def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, }); self.lower_item_id_use_tree(nested, id, vec); } @@ -206,7 +206,7 @@ impl<'hir> LoweringContext<'_, 'hir> { iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { vec.push(hir::ItemId { - def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, }); } } @@ -220,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let attrs = self.lower_attrs(hir_id, &i.attrs); 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(), + owner_id: hir_id.expect_owner(), ident: self.lower_ident(ident), kind, vis_span, @@ -562,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: hir::OwnerId { def_id: new_id }, + owner_id: hir::OwnerId { def_id: new_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -640,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: hir::OwnerId { def_id: new_hir_id }, + owner_id: hir::OwnerId { def_id: new_hir_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -660,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> { 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(); + let owner_id = hir_id.expect_owner(); self.lower_attrs(hir_id, &i.attrs); let item = hir::ForeignItem { - def_id, + owner_id, ident: self.lower_ident(i.ident), kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { @@ -702,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -845,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(hir_id, &i.attrs); let item = hir::TraitItem { - def_id: trait_item_def_id, + owner_id: trait_item_def_id, ident: self.lower_ident(i.ident), generics, kind, @@ -864,7 +864,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; + let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), @@ -931,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); let item = hir::ImplItem { - def_id: hir_id.expect_owner(), + owner_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), generics, kind, @@ -944,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { - id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, + id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), kind: match &i.kind { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 427b71722ab..ff29d15f1b5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1574,7 +1574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::OpaqueDef( - hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } }, lifetimes, in_trait, ) @@ -1593,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Generate an `type Foo = impl Trait;` declaration. trace!("registering opaque type with id {:#?}", opaque_ty_id); let opaque_ty_item = hir::Item { - def_id: hir::OwnerId { def_id: opaque_ty_id }, + owner_id: hir::OwnerId { def_id: opaque_ty_id }, ident: Ident::empty(), kind: opaque_ty_item_kind, vis_span: self.lower_span(span.shrink_to_lo()), @@ -2044,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::OpaqueDef( - hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } }, generic_args, in_trait, ); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0f11c176652..546010135a7 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; -use rustc_ast::{PatKind, RangeEnd, VariantData}; +use rustc_ast::{PatKind, RangeEnd}; use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; @@ -116,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { - let has_fields = variants.iter().any(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => true, - VariantData::Unit(..) => false, - }); - - let discriminant_spans = variants - .iter() - .filter(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) - .collect::<Vec<_>>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = feature_err( - &self.sess.parse_sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.data { - VariantData::Struct(..) => { - err.span_label(variant.span, "struct variant defined here"); - } - VariantData::Tuple(..) => { - err.span_label(variant.span, "tuple variant defined here"); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - /// Feature gate `impl Trait` inside `type Alias = $type_expr;`. fn check_impl_trait(&self, ty: &ast::Ty) { struct ImplTraitVisitor<'a> { @@ -273,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => { - for variant in variants { - match (&variant.data, &variant.disr_expr) { - (ast::VariantData::Unit(..), _) => {} - (_, Some(disr_expr)) => gate_feature_post!( - &self, - arbitrary_enum_discriminant, - disr_expr.value.span, - "discriminants on non-unit variants are experimental" - ), - _ => {} - } - } - - let has_feature = self.features.arbitrary_enum_discriminant; - if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - self.maybe_report_invalid_custom_discriminants(&variants); - } - } - ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => { if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 58aeb43ef97..df04128135b 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -92,7 +92,7 @@ pub struct OutlivesConstraint<'tcx> { pub span: Span, /// What caused this constraint? - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, /// Variance diagnostic information pub variance_info: VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3f5d9fb6206..583bc2e281d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -983,7 +983,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err: &mut Diagnostic, location: Location, issued_borrow: &BorrowData<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) { let used_in_call = matches!( explanation, @@ -1333,7 +1333,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans<'tcx>, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { debug!( "report_local_value_does_not_live_long_enough(\ @@ -1539,7 +1539,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, proper_span: Span, - explanation: BorrowExplanation, + explanation: BorrowExplanation<'tcx>, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation @@ -1653,7 +1653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow: &BorrowData<'tcx>, borrow_span: Span, return_span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, ) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> { let return_kind = match category { @@ -1748,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use_span: UseSpans<'tcx>, var_span: Span, fr_name: &RegionName, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraint_span: Span, captured_var: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 545237bb392..582d683dd35 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -21,7 +21,7 @@ use crate::{ use super::{find_use, RegionName, UseSpans}; #[derive(Debug)] -pub(crate) enum BorrowExplanation { +pub(crate) enum BorrowExplanation<'tcx> { UsedLater(LaterUseKind, Span, Option<Span>), UsedLaterInLoop(LaterUseKind, Span, Option<Span>), UsedLaterWhenDropped { @@ -30,7 +30,7 @@ pub(crate) enum BorrowExplanation { should_note_order: bool, }, MustBeValidFor { - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, from_closure: bool, span: Span, region_name: RegionName, @@ -49,7 +49,7 @@ pub(crate) enum LaterUseKind { Other, } -impl<'tcx> BorrowExplanation { +impl<'tcx> BorrowExplanation<'tcx> { pub(crate) fn is_explained(&self) -> bool { !matches!(self, BorrowExplanation::Unexplained) } @@ -284,7 +284,7 @@ impl<'tcx> BorrowExplanation { fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut Diagnostic, - category: &ConstraintCategory, + category: &ConstraintCategory<'tcx>, span: Span, region_name: &RegionName, ) { @@ -316,7 +316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) { + ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) { let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint( borrow_region, NllRegionVariableOrigin::FreeRegion, @@ -348,7 +348,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, borrow: &BorrowData<'tcx>, kind_place: Option<(WriteKind, Place<'tcx>)>, - ) -> BorrowExplanation { + ) -> BorrowExplanation<'tcx> { let regioncx = &self.regioncx; let body: &Body<'_> = &self.body; let tcx = self.infcx.tcx; diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 245ea07d120..35c3df76899 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder { pub(crate) fn intermediate_suggestion( &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'_>, diag: &mut Diagnostic, ) { // Emit an intermediate note. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b619537f317..15230718dc0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -2,7 +2,6 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. -use either::Either; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; @@ -17,7 +16,7 @@ use rustc_infer::infer::{ NllRegionVariableOrigin, RelateParamBound, }; use rustc_middle::hir::place::PlaceBase; -use rustc_middle::mir::{ConstraintCategory, ReturnConstraint, TerminatorKind}; +use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Region; use rustc_middle::ty::TypeVisitor; @@ -40,7 +39,7 @@ use crate::{ MirBorrowckCtxt, }; -impl ConstraintDescription for ConstraintCategory { +impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. match self { @@ -116,7 +115,7 @@ pub(crate) enum RegionErrorKind<'tcx> { /// Information about the various region constraints involved in a borrow checker error. #[derive(Clone, Debug)] -pub struct ErrorConstraintInfo { +pub struct ErrorConstraintInfo<'tcx> { // fr: outlived_fr pub(super) fr: RegionVid, pub(super) fr_is_local: bool, @@ -124,7 +123,7 @@ pub struct ErrorConstraintInfo { pub(super) outlived_fr_is_local: bool, // Category and span for best blame constraint - pub(super) category: ConstraintCategory, + pub(super) category: ConstraintCategory<'tcx>, pub(super) span: Span, } @@ -499,7 +498,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_fnmut_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, kind: ReturnConstraint, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; @@ -572,7 +571,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn report_escaping_data_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { span, category, .. } = errci; @@ -676,7 +675,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` fn report_general_error( &self, - errci: &ErrorConstraintInfo, + errci: &ErrorConstraintInfo<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let ErrorConstraintInfo { fr, @@ -789,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag: &mut Diagnostic, f: Region<'tcx>, o: Region<'tcx>, - category: &ConstraintCategory, + category: &ConstraintCategory<'tcx>, ) { if !o.is_static() { return; @@ -797,12 +796,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; - let instance = - if let ConstraintCategory::CallArgument(location) = category - && let Either::Right(term) = self.body.stmt_at(*location) - && let TerminatorKind::Call { func, .. } = &term.kind - { - let func_ty = func.ty(self.body, tcx); + let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category { let (fn_did, substs) = match func_ty.kind() { ty::FnDef(fn_did, substs) => (fn_did, substs), _ => return, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 85b9bde2c81..8b63294fbab 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -91,7 +91,7 @@ pub struct RegionInferenceContext<'tcx> { /// Map closure bounds to a `Span` that should be used for error reporting. closure_bounds_mapping: - FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>, + FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>, /// Map universe indexes to information on why we created it. universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, @@ -267,7 +267,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, closure_bounds_mapping: FxHashMap< Location, - FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>, + FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>, >, universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, type_tests: Vec<TypeTest<'tcx>>, @@ -1807,7 +1807,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn retrieve_closure_constraint_info( &self, constraint: OutlivesConstraint<'tcx>, - ) -> Option<(ConstraintCategory, Span)> { + ) -> Option<(ConstraintCategory<'tcx>, Span)> { match constraint.locations { Locations::All(_) => None, Locations::Single(loc) => { @@ -1822,7 +1822,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, - ) -> (ConstraintCategory, ObligationCause<'tcx>) { + ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) { let BlameConstraint { category, cause, .. } = self .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2)) .0; @@ -2362,7 +2362,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx #[derive(Clone, Debug)] pub struct BlameConstraint<'tcx> { - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, pub from_closure: bool, pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 11a57ef2621..465f353aaa3 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -263,13 +263,11 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - match infcx.register_hidden_type( - OpaqueTypeKey { def_id, substs: id_substs }, - ObligationCause::misc(instantiated_ty.span, body_id), - param_env, - definition_ty, - origin, - ) { + let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs); + match infcx + .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env) + .eq(opaque_ty, definition_ty) + { Ok(infer_ok) => { for obligation in infer_ok.obligations { fulfillment_cx.register_predicate_obligation(&infcx, obligation); @@ -280,7 +278,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { .err_ctxt() .report_mismatched_types( &ObligationCause::misc(instantiated_ty.span, body_id), - self.tcx.mk_opaque(def_id.to_def_id(), id_substs), + opaque_ty, definition_ty, err, ) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 459ecfe17e3..a581726a15c 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn fully_perform_op<R: fmt::Debug, Op>( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, op: Op, ) -> Fallible<R> where @@ -85,7 +85,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, trait_ref: ty::TraitRef<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { @@ -124,7 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { for predicate in predicates { let predicate = predicate.to_predicate(self.tcx()); @@ -139,7 +139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, predicate: ty::Predicate<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { let param_env = self.param_env; self.fully_perform_op( @@ -164,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, value: T, location: impl NormalizeLocation, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> T where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index d7e5a118a2e..d5bfc2f5208 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } @@ -50,7 +50,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, locations: Locations, span: Span, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { Self { @@ -175,7 +175,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { &mut self, sup: ty::RegionVid, sub: ty::RegionVid, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { let category = match self.category { ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category, @@ -203,7 +203,7 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<' _origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - constraint_category: ConstraintCategory, + constraint_category: ConstraintCategory<'tcx>, ) { let b = self.to_region_vid(b); let a = self.to_region_vid(a); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 00cacd515a1..3c1c3ab45ce 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -942,7 +942,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>, pub(crate) closure_bounds_mapping: - FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>, + FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>, pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>, @@ -1133,7 +1133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn push_region_constraints( &mut self, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, data: &QueryRegionConstraints<'tcx>, ) { debug!("constraints generated: {:#?}", data); @@ -1158,7 +1158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { // Use this order of parameters because the sup type is usually the // "expected" type in diagnostics. @@ -1171,7 +1171,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { self.relate_types(expected, ty::Variance::Invariant, found, locations, category) } @@ -1183,7 +1183,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, user_ty: &UserTypeProjection, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); @@ -1618,12 +1618,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } + let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind { + Some(func.ty(body, self.infcx.tcx)) + } else { + None + }; + debug!(?func_ty); + for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if from_hir_call { - ConstraintCategory::CallArgument(term_location) + ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty)) } else { ConstraintCategory::Boring }; @@ -1776,7 +1783,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. let erased_ty = tcx.erase_regions(ty); - if !erased_ty.is_sized(tcx.at(span), self.param_env) { + if !erased_ty.is_sized(tcx, self.param_env) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return // slot or local, so to find all unsized rvalues it is enough diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index b53360ea61b..4f2dc263bf5 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::NllRegionVariableOrigin; -use rustc_infer::traits::ObligationCause; +use rustc_infer::traits::PredicateObligations; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::TypeRelation; @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { v: ty::Variance, b: Ty<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { TypeRelating::new( self.infcx, @@ -45,7 +45,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { a: ty::SubstsRef<'tcx>, b: ty::SubstsRef<'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) -> Fallible<()> { TypeRelating::new( self.infcx, @@ -64,7 +64,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { locations: Locations, /// What category do we assign the resulting `'a: 'b` relationships? - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, /// Information so that error reporting knows what types we are relating /// when reporting a bound region error. @@ -75,7 +75,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, universe_info: UniverseInfo<'tcx>, ) -> Self { Self { type_checker, locations, category, universe_info } @@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> true } - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: PredicateObligations<'tcx>, ) -> Result<(), TypeError<'tcx>> { - let param_env = self.param_env(); - let span = self.span(); - let def_id = self.type_checker.body.source.def_id().expect_local(); - let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id); - let cause = ObligationCause::misc(span, body_id); self.type_checker .fully_perform_op( self.locations, self.category, InstantiateOpaqueType { - obligations: self - .type_checker - .infcx - .handle_opaque_type(a, b, a_is_expected, &cause, param_env)? - .obligations, + obligations, // These fields are filled in during execution of the operation base_universe: None, region_constraints: None, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 009f3c783d4..750f1fe121f 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -210,8 +210,15 @@ impl CfgEval<'_, '_> { } impl MutVisitor for CfgEval<'_, '_> { + #[instrument(level = "trace", skip(self))] fn visit_expr(&mut self, expr: &mut P<ast::Expr>) { - self.cfg.configure_expr(expr); + self.cfg.configure_expr(expr, false); + mut_visit::noop_visit_expr(expr, self); + } + + #[instrument(level = "trace", skip(self))] + fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) { + self.cfg.configure_expr(expr, true); mut_visit::noop_visit_expr(expr, self); } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index a41b561598f..1db44502742 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -770,11 +770,7 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(null_op, ty) => { - assert!( - lval.layout() - .ty - .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()) - ); + assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index d4bc3543b2d..148b66d959e 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, }; -use rustc_span::DUMMY_SP; use cranelift_module::*; @@ -291,7 +290,7 @@ fn data_id_for_static( let is_mutable = if tcx.is_mutable_static(def_id) { true } else { - !ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) + !ty.is_freeze(tcx, ParamEnv::reveal_all()) }; let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 8158e8dd011..bdc6a91cf6a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -5,7 +5,6 @@ use crate::common::TypeKind; use crate::mir::place::PlaceRef; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty}; -use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use rustc_target::abi::{AddressSpace, Integer}; @@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { let param_env = ty::ParamEnv::reveal_all(); - if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) { + if ty.is_sized(self.tcx(), param_env) { return false; } diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index cdcebb61c2e..f1674d04f8d 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -25,10 +25,12 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return /// `Constness::NotConst`. fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().get(hir_id) { - hir::Node::Ctor(_) => hir::Constness::Const, + let def_id = def_id.expect_local(); + let node = tcx.hir().get_by_def_id(def_id); + match node { + hir::Node::Ctor(_) => hir::Constness::Const, + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness, hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => { // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other // foreign items cannot be evaluated at compile-time. @@ -39,62 +41,20 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { }; if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } + _ => { + if let Some(fn_kind) = node.fn_kind() { + if fn_kind.constness() == hir::Constness::Const { + return hir::Constness::Const; + } - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - if tcx.is_const_default_method(def_id) => - { - hir::Constness::Const - } - - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. }) - | hir::Node::AnonConst(_) - | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - header: hir::FnHeader { constness: hir::Constness::Const, .. }, - .. - }, - .., - ), - .. - }) => hir::Constness::Const, - - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - let parent_hir_id = tcx.hir().get_parent_node(hir_id); - match tcx.hir().get(parent_hir_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - _ => span_bug!( - tcx.def_span(parent_hir_id.owner), - "impl item's parent node is not an impl", - ), + // If the function itself is not annotated with `const`, it may still be a `const fn` + // if it resides in a const trait impl. + let is_const = is_parent_const_impl_raw(tcx, def_id); + if is_const { hir::Constness::Const } else { hir::Constness::NotConst } + } else { + hir::Constness::NotConst } } - - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), - .. - }) - | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), - .. - }) => *constness, - - _ => hir::Constness::NotConst, } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e5acacd9188..35d58d2f638 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -2,10 +2,10 @@ use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use std::borrow::Borrow; -use std::collections::hash_map::Entry; use std::hash::Hash; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::IndexEntry; use std::fmt; use rustc_ast::Mutability; @@ -107,18 +107,18 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { } } -impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> { +impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> { #[inline(always)] fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool where K: Borrow<Q>, { - FxHashMap::contains_key(self, k) + FxIndexMap::contains_key(self, k) } #[inline(always)] fn insert(&mut self, k: K, v: V) -> Option<V> { - FxHashMap::insert(self, k, v) + FxIndexMap::insert(self, k, v) } #[inline(always)] @@ -126,7 +126,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> { where K: Borrow<Q>, { - FxHashMap::remove(self, k) + FxIndexMap::remove(self, k) } #[inline(always)] @@ -148,8 +148,8 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> { #[inline(always)] fn get_mut_or<E>(&mut self, k: K, vacant: impl FnOnce() -> Result<V, E>) -> Result<&mut V, E> { match self.entry(k) { - Entry::Occupied(e) => Ok(e.into_mut()), - Entry::Vacant(e) => { + IndexEntry::Occupied(e) => Ok(e.into_mut()), + IndexEntry::Vacant(e) => { let v = vacant()?; Ok(e.insert(v)) } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index a964fe8465e..f4da1188395 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -212,7 +212,7 @@ fn create_pointee_place<'tcx>( ) -> MPlaceTy<'tcx> { let tcx = ecx.tcx.tcx; - if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) { + if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) { // We need to create `Allocation`s for custom DSTs let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx); @@ -398,7 +398,7 @@ fn valtree_into_mplace<'tcx>( let mut place_inner = match ty.kind() { ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(), - _ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) + _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) && i == branches.len() - 1 => { // Note: For custom DSTs we need to manually process the last unsized field. diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f980e606b93..269ae15d497 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -138,23 +138,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + /// Handles 'IntToInt' and 'IntToFloat' casts. pub fn int_to_int_or_float( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate<M::Provenance>> { - if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()) - && (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()) - { - let scalar = src.to_scalar(); - Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) - } else { - bug!("Unexpected cast from type {:?}", src.layout.ty) - } + assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool()); + assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char()); + + Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into()) } + /// Handles 'FloatToFloat' and 'FloatToInt' casts. pub fn float_to_float_or_int( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate<M::Provenance>> { @@ -176,35 +174,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts. pub fn ptr_to_ptr( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate<M::Provenance>> { + assert!(src.layout.ty.is_any_ptr()); + assert!(cast_ty.is_unsafe_ptr()); // Handle casting any ptr to raw ptr (might be a fat ptr). - if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() { - let dest_layout = self.layout_of(cast_ty)?; - if dest_layout.size == src.layout.size { - // Thin or fat pointer that just hast the ptr kind of target type changed. - return Ok(**src); - } else { - // Casting the metadata away from a fat ptr. - assert_eq!(src.layout.size, 2 * self.pointer_size()); - assert_eq!(dest_layout.size, self.pointer_size()); - assert!(src.layout.ty.is_unsafe_ptr()); - return match **src { - Immediate::ScalarPair(data, _) => Ok(data.into()), - Immediate::Scalar(..) => span_bug!( - self.cur_span(), - "{:?} input to a fat-to-thin cast ({:?} -> {:?})", - *src, - src.layout.ty, - cast_ty - ), - Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), - }; - } + let dest_layout = self.layout_of(cast_ty)?; + if dest_layout.size == src.layout.size { + // Thin or fat pointer that just hast the ptr kind of target type changed. + return Ok(**src); } else { - bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty); + // Casting the metadata away from a fat ptr. + assert_eq!(src.layout.size, 2 * self.pointer_size()); + assert_eq!(dest_layout.size, self.pointer_size()); + assert!(src.layout.ty.is_unsafe_ptr()); + return match **src { + Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::Scalar(..) => span_bug!( + self.cur_span(), + "{:?} input to a fat-to-thin cast ({:?} -> {:?})", + *src, + src.layout.ty, + cast_ty + ), + Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), + }; } } @@ -226,7 +222,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn pointer_from_exposed_address_cast( - &mut self, + &self, src: &ImmTy<'tcx, M::Provenance>, cast_ty: Ty<'tcx>, ) -> InterpResult<'tcx, Immediate<M::Provenance>> { @@ -243,6 +239,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Scalar::from_maybe_pointer(ptr, self).into()) } + /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input + /// type (basically everything with a scalar layout) to int/float/char types. pub fn cast_from_int_like( &self, scalar: Scalar<M::Provenance>, // input value (there is no ScalarTy so we separate data+layout) @@ -282,6 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }) } + /// Low-level cast helper function. Converts an apfloat `f` into int or float types. fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::Provenance> where F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index d2e0a0dd240..a9063ad31cf 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -468,7 +468,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx, self.param_env) + ty.is_freeze(*self.tcx, self.param_env) } pub fn load_mir( diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f72ae7413e3..6809a42dc45 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -15,7 +15,7 @@ //! that contains allocations whose mutability we cannot identify.) use super::validity::RefTracking; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpResult; @@ -37,7 +37,7 @@ pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine< ExtraFnVal = !, FrameExtra = (), AllocExtra = (), - MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>, + MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>, >; struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> { @@ -47,7 +47,7 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_ev ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>, /// A list of all encountered allocations. After type-based interning, we traverse this list to /// also intern allocations that are only referenced by a raw pointer or inside a union. - leftover_allocations: &'rt mut FxHashSet<AllocId>, + leftover_allocations: &'rt mut FxIndexSet<AllocId>, /// The root kind of the value that we're looking at. This field is never mutated for a /// particular allocation. It is primarily used to make as many allocations as possible /// read-only so LLVM can place them in const memory. @@ -79,7 +79,7 @@ struct IsStaticOrFn; /// to account for (e.g. for vtables). fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, - leftover_allocations: &'rt mut FxHashSet<AllocId>, + leftover_allocations: &'rt mut FxIndexSet<AllocId>, alloc_id: AllocId, mode: InternMode, ty: Option<Ty<'tcx>>, @@ -114,7 +114,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: if let InternMode::Static(mutability) = mode { // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume // no interior mutability. - let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env)); + let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env)); // For statics, allocation mutability is the combination of place mutability and // type mutability. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. @@ -355,7 +355,7 @@ pub fn intern_const_alloc_recursive< // `leftover_allocations` collects *all* allocations we see, because some might not // be available in a typed way. They get interned at the end. let mut ref_tracking = RefTracking::empty(); - let leftover_allocations = &mut FxHashSet::default(); + let leftover_allocations = &mut FxIndexSet::default(); // start with the outermost allocation intern_shallow( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index 7e4c5fcb031..ffdb8de5b6c 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -4,7 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData; use rustc_middle::mir::interpret::{Allocation, ConstAllocation}; use rustc_middle::ty::{ self, - print::{PrettyPrinter, Print, Printer}, + print::{with_no_verbose_constants, PrettyPrinter, Print, Printer}, subst::{GenericArg, GenericArgKind}, Ty, TyCtxt, }; @@ -190,7 +190,9 @@ impl Write for AbsolutePathPrinter<'_> { /// Directly returns an `Allocation` containing an absolute path representation of the given type. pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { - let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; + let path = with_no_verbose_constants!( + AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path + ); let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); tcx.intern_const_alloc(alloc) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 530e252b7c0..351152eba01 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -426,7 +426,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type ExtraFnVal = !; type MemoryMap = - rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>; + rustc_data_structures::fx::FxIndexMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>; const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory type AllocExtra = (); diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 719588a936c..0c212cf59e1 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -554,6 +554,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { val: &mir::ConstantKind<'tcx>, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + // FIXME(const_prop): normalization needed b/c const prop lint in + // `mir_drops_elaborated_and_const_checked`, which happens before + // optimized MIR. Only after optimizing the MIR can we guarantee + // that the `RevealAll` pass has happened and that the body's consts + // are normalized, so any call to resolve before that needs to be + // manually normalized. + let val = self.tcx.normalize_erasing_regions(self.param_env, *val); match val { mir::ConstantKind::Ty(ct) => { match ct.kind() { @@ -585,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } } - mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout), + mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d4146c24241..8aa56c275d9 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -15,7 +15,6 @@ use rustc_middle::mir::interpret::InterpError; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::DUMMY_SP; use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use std::hash::Hash; @@ -726,7 +725,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) -> InterpResult<'tcx> { // Special check preventing `UnsafeCell` inside unions in the inner part of constants. if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) { - if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) { + if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" }); } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 230f841cf4d..443c01fdb90 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -22,7 +22,6 @@ Rust MIR: a lowered representation of Rust. #![feature(yeet_expr)] #![feature(is_some_and)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index b77b213b51a..335992342a6 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; -use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::{ self, ImplSource, Obligation, ObligationCause, SelectionContext, }; @@ -92,7 +91,7 @@ impl Qualif for HasMutInterior { } fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) + !ty.is_freeze(cx.tcx, cx.param_env) } fn in_adt_inherently<'tcx>( diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 60c1e495029..805e6096b35 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -8,7 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementK use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::JoinSemiLattice; use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces}; -use rustc_span::DUMMY_SP; use std::fmt; use std::marker::PhantomData; @@ -120,10 +119,7 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place - .ty(self.ccx.body, self.ccx.tcx) - .ty - .is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env) + !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env) } } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 4b219300739..f3ae16da43b 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -41,10 +41,6 @@ pub struct PromoteTemps<'tcx> { } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { - fn phase_change(&self) -> Option<MirPhase> { - Some(MirPhase::Analysis(AnalysisPhase::Initial)) - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 7f78d963e9f..81b82a21fa1 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -235,9 +235,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // `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; - let span = self.body.source_info(location).span; - if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty)); } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 467ac401d08..3a2000233c5 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -22,6 +22,7 @@ #![feature(new_uninit)] #![feature(once_cell)] #![feature(rustc_attrs)] +#![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] #![feature(vec_into_raw_parts)] @@ -86,6 +87,7 @@ pub mod steal; pub mod tagged_ptr; pub mod temp_dir; pub mod unhash; +pub mod unord; pub use ena::undo_log; pub use ena::unify; diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs new file mode 100644 index 00000000000..c015f1232cd --- /dev/null +++ b/compiler/rustc_data_structures/src/unord.rs @@ -0,0 +1,382 @@ +//! This module contains collection types that don't expose their internal +//! ordering. This is a useful property for deterministic computations, such +//! as required by the query system. + +use rustc_hash::{FxHashMap, FxHashSet}; +use smallvec::SmallVec; +use std::{ + borrow::Borrow, + hash::Hash, + iter::{Product, Sum}, +}; + +use crate::{ + fingerprint::Fingerprint, + stable_hasher::{HashStable, StableHasher, ToStableHashKey}, +}; + +/// `UnordItems` is the order-less version of `Iterator`. It only contains methods +/// that don't (easily) expose an ordering of the underlying items. +/// +/// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This +/// is to reduce the risk of accidentally leaking the internal order via the closure +/// environment. Otherwise one could easily do something like +/// +/// ```rust,ignore (pseudo code) +/// let mut ordered = vec![]; +/// unordered_items.all(|x| ordered.push(x)); +/// ``` +/// +/// It's still possible to do the same thing with an `Fn` by using interior mutability, +/// but the chance of doing it accidentally is reduced. +pub struct UnordItems<T, I: Iterator<Item = T>>(I); + +impl<T, I: Iterator<Item = T>> UnordItems<T, I> { + #[inline] + pub fn map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>> { + UnordItems(self.0.map(f)) + } + + #[inline] + pub fn all<U, F: Fn(T) -> bool>(mut self, f: F) -> bool { + self.0.all(f) + } + + #[inline] + pub fn any<U, F: Fn(T) -> bool>(mut self, f: F) -> bool { + self.0.any(f) + } + + #[inline] + pub fn filter<U, F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>> { + UnordItems(self.0.filter(f)) + } + + #[inline] + pub fn filter_map<U, F: Fn(T) -> Option<U>>( + self, + f: F, + ) -> UnordItems<U, impl Iterator<Item = U>> { + UnordItems(self.0.filter_map(f)) + } + + #[inline] + pub fn max(self) -> Option<T> + where + T: Ord, + { + self.0.max() + } + + #[inline] + pub fn min(self) -> Option<T> + where + T: Ord, + { + self.0.min() + } + + #[inline] + pub fn sum<S>(self) -> S + where + S: Sum<T>, + { + self.0.sum() + } + + #[inline] + pub fn product<S>(self) -> S + where + S: Product<T>, + { + self.0.product() + } + + #[inline] + pub fn count(self) -> usize { + self.0.count() + } +} + +impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> { + #[inline] + pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> { + UnordItems(self.0.cloned()) + } +} + +impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> { + #[inline] + pub fn copied(self) -> UnordItems<T, impl Iterator<Item = T>> { + UnordItems(self.0.copied()) + } +} + +impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> { + pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T> + where + T: ToStableHashKey<HCX>, + { + let mut items: Vec<T> = self.0.collect(); + items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + items + } + + pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]> + where + T: ToStableHashKey<HCX>, + { + let mut items: SmallVec<[T; LEN]> = self.0.collect(); + items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + items + } +} + +/// This is a set collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for set-like collections the +/// keys of which don't have a semantic ordering. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordSet<V: Eq + Hash> { + inner: FxHashSet<V>, +} + +impl<V: Eq + Hash> Default for UnordSet<V> { + fn default() -> Self { + Self { inner: FxHashSet::default() } + } +} + +impl<V: Eq + Hash> UnordSet<V> { + #[inline] + pub fn new() -> Self { + Self { inner: Default::default() } + } + + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn insert(&mut self, v: V) -> bool { + self.inner.insert(v) + } + + #[inline] + pub fn contains<Q: ?Sized>(&self, v: &Q) -> bool + where + V: Borrow<Q>, + Q: Hash + Eq, + { + self.inner.contains(v) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordSet from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) { + self.inner.extend(items.0) + } +} + +impl<V: Hash + Eq> Extend<V> for UnordSet<V> { + fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +/// This is a map collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for map-like collections the +/// keys of which don't have a semantic ordering. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordMap<K: Eq + Hash, V> { + inner: FxHashMap<K, V>, +} + +impl<K: Eq + Hash, V> Default for UnordMap<K, V> { + fn default() -> Self { + Self { inner: FxHashMap::default() } + } +} + +impl<K: Hash + Eq, V> Extend<(K, V)> for UnordMap<K, V> { + fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { + self.inner.extend(iter) + } +} + +impl<K: Eq + Hash, V> UnordMap<K, V> { + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn insert(&mut self, k: K, v: V) -> Option<V> { + self.inner.insert(k, v) + } + + #[inline] + pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool + where + K: Borrow<Q>, + Q: Hash + Eq, + { + self.inner.contains_key(k) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator<Item = (&'a K, &'a V)>> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordMap from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) { + self.inner.extend(items.0) + } +} + +impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> for UnordMap<K, V> { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +/// This is a collection type that tries very hard to not expose +/// any internal iteration. This is a useful property when trying to +/// uphold the determinism invariants imposed by the query system. +/// +/// This collection type is a good choice for collections the +/// keys of which don't have a semantic ordering and don't implement +/// `Hash` or `Eq`. +/// +/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) +/// for more information. +#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)] +pub struct UnordBag<V> { + inner: Vec<V>, +} + +impl<V> UnordBag<V> { + #[inline] + pub fn new() -> Self { + Self { inner: Default::default() } + } + + #[inline] + pub fn len(&self) -> usize { + self.inner.len() + } + + #[inline] + pub fn push(&mut self, v: V) { + self.inner.push(v); + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> { + UnordItems(self.inner.iter()) + } + + #[inline] + pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> { + UnordItems(self.inner.into_iter()) + } + + // We can safely extend this UnordSet from a set of unordered values because that + // won't expose the internal ordering anywhere. + #[inline] + pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) { + self.inner.extend(items.0) + } +} + +impl<T> Extend<T> for UnordBag<T> { + fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { + self.inner.extend(iter) + } +} + +impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordBag<V> { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + hash_iter_order_independent(self.inner.iter(), hcx, hasher); + } +} + +fn hash_iter_order_independent< + HCX, + T: HashStable<HCX>, + I: Iterator<Item = T> + ExactSizeIterator, +>( + mut it: I, + hcx: &mut HCX, + hasher: &mut StableHasher, +) { + let len = it.len(); + len.hash_stable(hcx, hasher); + + match len { + 0 => { + // We're done + } + 1 => { + // No need to instantiate a hasher + it.next().unwrap().hash_stable(hcx, hasher); + } + _ => { + let mut accumulator = Fingerprint::ZERO; + for item in it { + let mut item_hasher = StableHasher::new(); + item.hash_stable(hcx, &mut item_hasher); + let item_fingerprint: Fingerprint = item_hasher.finish(); + accumulator = accumulator.combine_commutative(item_fingerprint); + } + accumulator.hash_stable(hcx, hasher); + } + } +} + +// Do not implement IntoIterator for the collections in this module. +// They only exist to hide iteration order in the first place. +impl<T> !IntoIterator for UnordBag<T> {} +impl<V> !IntoIterator for UnordSet<V> {} +impl<K, V> !IntoIterator for UnordMap<K, V> {} +impl<T, I> !IntoIterator for UnordItems<T, I> {} diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 7edbb6f757c..cfa734c7df3 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -427,18 +427,6 @@ fn run_compiler( }) } -#[cfg(unix)] -pub fn set_sigpipe_handler() { - unsafe { - // Set the SIGPIPE signal handler, so that an EPIPE - // will cause rustc to terminate, as expected. - assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR); - } -} - -#[cfg(windows)] -pub fn set_sigpipe_handler() {} - // Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md index 7347e6654c5..9536fdbf0df 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0732.md +++ b/compiler/rustc_error_codes/src/error_codes/E0732.md @@ -3,8 +3,6 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`. Erroneous code example: ```compile_fail,E0732 -#![feature(arbitrary_enum_discriminant)] - enum Enum { // error! Unit = 1, Tuple() = 2, @@ -20,8 +18,6 @@ is a well-defined way to extract a variant's discriminant from a value; for instance: ``` -#![feature(arbitrary_enum_discriminant)] - #[repr(u8)] enum Enum { Unit = 3, diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 357c6900a70..74088f4dfbe 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -93,7 +93,7 @@ hir_analysis_expected_default_return_type = expected `()` because of default ret hir_analysis_expected_return_type = expected `{$expected}` because of return type hir_analysis_unconstrained_opaque_type = unconstrained opaque type - .note = `{$name}` must be used in combination with a concrete type within the same module + .note = `{$name}` must be used in combination with a concrete type within the same {$what} hir_analysis_missing_type_params = the type {$parameterCount -> @@ -137,3 +137,16 @@ hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(l hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function + +hir_analysis_const_impl_for_non_const_trait = + const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]` + .suggestion = mark `{$trait_name}` as const + .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const` + .adding = adding a non-const method body in the future would be a breaking change + +hir_analysis_const_bound_for_non_const_trait = + ~const can only be applied to `#[const_trait]` traits + +hir_analysis_self_in_impl_self = + `Self` is not valid in the self type of an impl block + .note = replace `Self` with a different type diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a63fc0ca285..23f29a24fe7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -691,6 +691,24 @@ impl Diagnostic { suggestions: impl Iterator<Item = String>, applicability: Applicability, ) -> &mut Self { + self.span_suggestions_with_style( + sp, + msg, + suggestions, + applicability, + SuggestionStyle::ShowCode, + ) + } + + /// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`]. + pub fn span_suggestions_with_style( + &mut self, + sp: Span, + msg: impl Into<SubdiagnosticMessage>, + suggestions: impl Iterator<Item = String>, + applicability: Applicability, + style: SuggestionStyle, + ) -> &mut Self { let mut suggestions: Vec<_> = suggestions.collect(); suggestions.sort(); @@ -706,14 +724,15 @@ impl Diagnostic { self.push_suggestion(CodeSuggestion { substitutions, msg: self.subdiagnostic_message_to_diagnostic_message(msg), - style: SuggestionStyle::ShowCode, + style, applicability, }); self } - /// Prints out a message with multiple suggested edits of the code. - /// See also [`Diagnostic::span_suggestion()`]. + /// Prints out a message with multiple suggested edits of the code, where each edit consists of + /// multiple parts. + /// See also [`Diagnostic::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, msg: impl Into<SubdiagnosticMessage>, @@ -745,6 +764,7 @@ impl Diagnostic { }); self } + /// Prints out a message with a suggested edit of the code. If the suggestion is presented /// inline, it will only show the message and not the suggestion. /// diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 8d4e3640748..1d2b1298a68 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> { } /// If attributes are not allowed on expressions, emit an error for `attr` + #[instrument(level = "trace", skip(self))] pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if !self.features.map_or(true, |features| features.stmt_expr_attributes) { let mut err = feature_err( @@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> { } } - pub fn configure_expr(&self, expr: &mut P<ast::Expr>) { - for attr in expr.attrs.iter() { - self.maybe_emit_expr_attr_err(attr); + #[instrument(level = "trace", skip(self))] + pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) { + if !method_receiver { + for attr in expr.attrs.iter() { + self.maybe_emit_expr_attr_err(attr); + } } // If an expr is valid to cfg away it will have been removed by the diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 15e9a8db3c6..57713fb3cd6 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -50,6 +50,7 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option<P<ast::Expr>>), + MethodReceiverExpr(P<ast::Expr>), $($Kind($AstTy),)* } @@ -57,6 +58,7 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, + MethodReceiverExpr, $($Kind,)* } @@ -64,6 +66,7 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", + AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -72,6 +75,8 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), + AstFragmentKind::MethodReceiverExpr => + result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -98,6 +103,13 @@ macro_rules! ast_fragments { } } + pub fn make_method_receiver_expr(self) -> P<ast::Expr> { + match self { + AstFragment::MethodReceiverExpr(expr) => expr, + _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + } + } + $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, @@ -120,6 +132,7 @@ macro_rules! ast_fragments { } }); } + AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)* @@ -130,6 +143,7 @@ macro_rules! ast_fragments { match *self { AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr), AstFragment::OptExpr(None) => {} + AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr), $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] { visitor.$visit_ast_elt(ast_elt, $($args)*); @@ -222,6 +236,7 @@ impl AstFragmentKind { match self { AstFragmentKind::OptExpr | AstFragmentKind::Expr + | AstFragmentKind::MethodReceiverExpr | AstFragmentKind::Stmts | AstFragmentKind::Ty | AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false }, @@ -285,6 +300,9 @@ impl AstFragmentKind { AstFragmentKind::Expr => AstFragment::Expr( items.next().expect("expected exactly one expression").expect_expr(), ), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr( + items.next().expect("expected exactly one expression").expect_expr(), + ), AstFragmentKind::OptExpr => { AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)) } @@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>( AstFragment::Stmts(stmts) } AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?), AstFragmentKind::OptExpr => { if this.token != token::Eof { AstFragment::OptExpr(Some(this.parse_expr()?)) @@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> { } } +/// This struct is a hack to workaround unstable of `stmt_expr_attributes`. +/// It can be removed once that feature is stabilized. +struct MethodReceiverTag; +impl DummyAstNode for MethodReceiverTag { + fn dummy() -> MethodReceiverTag { + MethodReceiverTag + } +} +impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> { + type OutputTy = Self; + type AttrsTy = ast::AttrVec; + const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr; + fn descr() -> &'static str { + "an expression" + } + fn to_annotatable(self) -> Annotatable { + Annotatable::Expr(self.wrapped) + } + fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy { + AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag) + } + fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) { + noop_visit_expr(&mut self.wrapped, visitor) + } + fn is_mac_call(&self) -> bool { + matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) + } + fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) { + let node = self.wrapped.into_inner(); + match node.kind { + ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), + _ => unreachable!(), + } + } +} + struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>, @@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.visit_node(node) } + fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) { + visit_clobber(node, |node| { + let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag); + self.visit_node(&mut wrapper); + wrapper.wrapped + }) + } + fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> { self.flat_map_node(AstNodeWrapper::new(node, OptExprTag)) } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1e268542bcd..f6fe38174f7 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -250,6 +250,7 @@ fn expand_macro<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) + // FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match. let parser = parser_from_cx(sess, arg.clone()); // Try each arm's matchers. diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 3b0d5ddb97b..faaf3b3fea5 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -55,6 +55,7 @@ pub fn placeholder( }), AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), + AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()), AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { id, span, @@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander { } } + fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) { + match expr.kind { + ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(), + _ => noop_visit_expr(expr, self), + } + } + fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { match expr.kind { ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 54bf5a2c34b..db289a64046 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -53,6 +53,8 @@ declare_features! ( (accepted, abi_sysv64, "1.24.0", Some(36167), None), /// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`. (accepted, adx_target_feature, "1.61.0", Some(44839), None), + /// Allows explicit discriminants on non-unit enum variants. + (accepted, arbitrary_enum_discriminant, "CURRENT_RUSTC_VERSION", Some(60553), None), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "CURRENT_RUSTC_VERSION", Some(93333), None), /// Allows the definition of associated constants in `trait` or `impl` blocks. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1b8d683b133..4facb6140a3 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -292,8 +292,6 @@ declare_features! ( (incomplete, adt_const_params, "1.56.0", Some(95174), None), /// Allows defining an `#[alloc_error_handler]`. (active, alloc_error_handler, "1.29.0", Some(51540), None), - /// Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), /// Allows using `const` operands in inline assembly. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bc149e48d89..ef00c1ffc30 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2207,14 +2207,14 @@ pub struct FnSig<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct TraitItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl TraitItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2225,7 +2225,7 @@ impl TraitItemId { #[derive(Debug, HashStable_Generic)] pub struct TraitItem<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: TraitItemKind<'hir>, pub span: Span, @@ -2236,11 +2236,11 @@ impl TraitItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn trait_item_id(&self) -> TraitItemId { - TraitItemId { def_id: self.def_id } + TraitItemId { owner_id: self.owner_id } } } @@ -2271,14 +2271,14 @@ pub enum TraitItemKind<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ImplItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ImplItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2286,7 +2286,7 @@ impl ImplItemId { #[derive(Debug, HashStable_Generic)] pub struct ImplItem<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: ImplItemKind<'hir>, pub defaultness: Defaultness, @@ -2298,11 +2298,11 @@ impl ImplItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn impl_item_id(&self) -> ImplItemId { - ImplItemId { def_id: self.def_id } + ImplItemId { owner_id: self.owner_id } } } @@ -2418,6 +2418,30 @@ impl<'hir> Ty<'hir> { } final_ty } + + pub fn find_self_aliases(&self) -> Vec<Span> { + use crate::intravisit::Visitor; + struct MyVisitor(Vec<Span>); + impl<'v> Visitor<'v> for MyVisitor { + fn visit_ty(&mut self, t: &'v Ty<'v>) { + if matches!( + &t.kind, + TyKind::Path(QPath::Resolved( + _, + Path { res: crate::def::Res::SelfTyAlias { .. }, .. }, + )) + ) { + self.0.push(t.span); + return; + } + crate::intravisit::walk_ty(self, t); + } + } + + let mut my_visitor = MyVisitor(vec![]); + my_visitor.visit_ty(self); + my_visitor.0 + } } /// Not represented directly in the AST; referred to by name through a `ty_path`. @@ -2890,14 +2914,14 @@ impl<'hir> VariantData<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)] pub struct ItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -2907,7 +2931,7 @@ impl ItemId { #[derive(Debug, HashStable_Generic)] pub struct Item<'hir> { pub ident: Ident, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, pub vis_span: Span, @@ -2917,11 +2941,11 @@ impl Item<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn item_id(&self) -> ItemId { - ItemId { def_id: self.def_id } + ItemId { owner_id: self.owner_id } } } @@ -3134,14 +3158,14 @@ pub enum AssocItemKind { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ForeignItemId { - pub def_id: OwnerId, + pub owner_id: OwnerId, } impl ForeignItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } } @@ -3162,7 +3186,7 @@ pub struct ForeignItemRef { pub struct ForeignItem<'hir> { pub ident: Ident, pub kind: ForeignItemKind<'hir>, - pub def_id: OwnerId, + pub owner_id: OwnerId, pub span: Span, pub vis_span: Span, } @@ -3171,11 +3195,11 @@ impl ForeignItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id.def_id) + HirId::make_owner(self.owner_id.def_id) } pub fn foreign_item_id(&self) -> ForeignItemId { - ForeignItemId { def_id: self.def_id } + ForeignItemId { owner_id: self.owner_id } } } @@ -3267,10 +3291,10 @@ impl<'hir> OwnerNode<'hir> { pub fn def_id(self) -> OwnerId { match self { - OwnerNode::Item(Item { def_id, .. }) - | OwnerNode::TraitItem(TraitItem { def_id, .. }) - | OwnerNode::ImplItem(ImplItem { def_id, .. }) - | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id, + OwnerNode::Item(Item { owner_id, .. }) + | OwnerNode::TraitItem(TraitItem { owner_id, .. }) + | OwnerNode::ImplItem(ImplItem { owner_id, .. }) + | OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id, OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner, } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f3bde099b13..be77e6fd36a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -912,7 +912,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>( pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { // N.B., deliberately force a compilation error if/when new fields are added. - let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item; + let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; let hir_id = trait_item.hir_id(); visitor.visit_ident(ident); visitor.visit_generics(&generics); @@ -952,7 +952,7 @@ 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: _, + owner_id: _, ident, ref generics, ref kind, diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 06b7a65662e..23423e8f3b3 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -49,7 +49,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -58,7 +58,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -67,7 +67,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -76,7 +76,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.def_id.to_stable_hash_key(hcx) + self.owner_id.def_id.to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a0350c26d82..38f195dabb9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; @@ -275,6 +275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ); if let Some(b) = item_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -324,6 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option<Ty<'tcx>>, + constness: Option<ty::BoundConstness>, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, @@ -534,6 +536,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut substs_ctx, ); + if let Some(ty::BoundConstness::ConstIfConst) = constness + && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) + { + tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); + } + (substs, arg_count) } @@ -601,6 +609,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, + None, ); if let Some(b) = item_segment.args().bindings.first() { @@ -620,6 +629,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, trait_ref: &hir::TraitRef<'_>, self_ty: Ty<'tcx>, + constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); @@ -629,6 +639,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_ref.path.segments.last().unwrap(), true, + Some(constness), ) } @@ -655,6 +666,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, Some(self_ty), + Some(constness), ); let tcx = self.tcx(); @@ -680,6 +692,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative, &mut dup_bindings, binding_span.unwrap_or(binding.span), + constness, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -783,6 +796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, is_impl: bool, + constness: Option<ty::BoundConstness>, ) -> ty::TraitRef<'tcx> { let (substs, _) = self.create_substs_for_ast_trait_ref( span, @@ -790,6 +804,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty, trait_segment, is_impl, + constness, ); if let Some(b) = trait_segment.args().bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -805,6 +820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, is_impl: bool, + constness: Option<ty::BoundConstness>, ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); @@ -816,6 +832,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_segment.args(), trait_segment.infer_args, Some(self_ty), + constness, ) } @@ -1027,6 +1044,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative: bool, dup_bindings: &mut FxHashMap<DefId, Span>, path_span: Span, + constness: ty::BoundConstness, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait<T = X>`, we want to produce a // predicate like `<U as SomeTrait>::T = X`. This is somewhat @@ -1122,10 +1140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_ref.substs, ); - debug!( - "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}", - substs_trait_ref_and_assoc_item - ); + debug!(?substs_trait_ref_and_assoc_item); ty::ProjectionTy { item_def_id: assoc_item.def_id, @@ -1146,8 +1161,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); - debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); - debug!("late_bound_in_ty = {:?}", late_bound_in_ty); + debug!(?late_bound_in_trait_ref); + debug!(?late_bound_in_ty); // FIXME: point at the type params that don't have appropriate lifetimes: // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); @@ -1648,6 +1663,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Checks that `bounds` contains exactly one element and reports appropriate // errors otherwise. + #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)] fn one_bound_for_assoc_type<I>( &self, all_candidates: impl Fn() -> I, @@ -1677,10 +1693,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return Err(reported); } }; - debug!("one_bound_for_assoc_type: bound = {:?}", bound); + debug!(?bound); if let Some(bound2) = next_cand { - debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); + debug!(?bound2); let is_equality = is_equality(); let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); @@ -1776,6 +1792,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // parameter or `Self`. // NOTE: When this function starts resolving `Trait::AssocTy` successfully // it should also start reporting the `BARE_TRAIT_OBJECTS` lint. + #[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)] pub fn associated_path_to_ty( &self, hir_ref_id: hir::HirId, @@ -1793,8 +1810,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Res::Err }; - debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident); - // Check if we have an enum variant. let mut variant_resolution = None; if let ty::Adt(adt_def, _) = qself_ty.kind() { @@ -2050,6 +2065,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_def_id: DefId, trait_segment: &hir::PathSegment<'_>, item_segment: &hir::PathSegment<'_>, + constness: ty::BoundConstness, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2094,8 +2110,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: self_type={:?}", self_ty); - let trait_ref = - self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); + let trait_ref = self.ast_path_to_mono_trait_ref( + span, + trait_def_id, + self_ty, + trait_segment, + false, + Some(constness), + ); let item_substs = self.create_substs_for_associated_item( span, @@ -2534,12 +2556,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Res::Def(DefKind::AssocTy, def_id) => { debug_assert!(path.segments.len() >= 2); self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {}); + // HACK: until we support `<Type as ~const Trait>`, assume all of them are. + let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) { + ty::BoundConstness::ConstIfConst + } else { + ty::BoundConstness::NotConst + }; self.qpath_to_ty( span, opt_self_ty, def_id, &path.segments[path.segments.len() - 2], path.segments.last().unwrap(), + constness, ) } Res::PrimTy(prim_ty) => { @@ -2632,7 +2661,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); - let def_id = item_id.def_id.to_def_id(); + let def_id = item_id.owner_id.to_def_id(); match opaque_ty.kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { @@ -2658,6 +2687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &GenericArgs::none(), true, None, + None, ); EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) .subst(tcx, substs) @@ -2766,6 +2796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)] pub fn ty_of_fn( &self, hir_id: hir::HirId, @@ -2775,8 +2806,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generics: Option<&hir::Generics<'_>>, hir_ty: Option<&hir::Ty<'_>>, ) -> ty::PolyFnSig<'tcx> { - debug!("ty_of_fn"); - let tcx = self.tcx(); let bound_vars = tcx.late_bound_vars(hir_id); debug!(?bound_vars); @@ -2826,7 +2855,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), }; - debug!("ty_of_fn: output_ty={:?}", output_ty); + debug!(?output_ty); 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); @@ -2903,8 +2932,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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 trait_ref = self.instantiate_mono_trait_ref( + i.of_trait.as_ref()?, + self.ast_ty_to_ty(i.self_ty), + ty::BoundConstness::NotConst, + ); let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( tcx, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a1faf802519..b70ac02058d 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -114,7 +114,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b _ => { // Fallback case: allow `ManuallyDrop` and things that are `Copy`. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx.at(span), param_env) + || ty.is_copy_modulo_regions(tcx, param_env) } } } @@ -227,17 +227,17 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { return; } - let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id()); - let span = tcx.def_span(item.def_id.def_id); + let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id()); + let span = tcx.def_span(item.owner_id.def_id); - check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span); - if tcx.type_of(item.def_id.def_id).references_error() { + check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); + if tcx.type_of(item.owner_id.def_id).references_error() { return; } - if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() { + if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() { return; } - check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin); + check_opaque_meets_bounds(tcx, item.owner_id.def_id, substs, span, &origin); } /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result /// in "inheriting lifetimes". @@ -492,25 +492,25 @@ fn check_opaque_meets_bounds<'tcx>( fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { debug!( "check_item_type(it.def_id={:?}, it.name={})", - id.def_id, - tcx.def_path_str(id.def_id.to_def_id()) + id.owner_id, + tcx.def_path_str(id.owner_id.to_def_id()) ); let _indenter = indenter(); - match tcx.def_kind(id.def_id) { + match tcx.def_kind(id.owner_id) { DefKind::Static(..) => { - tcx.ensure().typeck(id.def_id.def_id); - maybe_check_static_with_link_section(tcx, id.def_id.def_id); - check_static_inhabited(tcx, id.def_id.def_id); + tcx.ensure().typeck(id.owner_id.def_id); + maybe_check_static_with_link_section(tcx, id.owner_id.def_id); + check_static_inhabited(tcx, id.owner_id.def_id); } DefKind::Const => { - tcx.ensure().typeck(id.def_id.def_id); + tcx.ensure().typeck(id.owner_id.def_id); } DefKind::Enum => { let item = tcx.hir().item(id); let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else { return; }; - check_enum(tcx, &enum_definition.variants, item.def_id.def_id); + check_enum(tcx, &enum_definition.variants, item.owner_id.def_id); } DefKind::Fn => {} // entirely within check_item_body DefKind::Impl => { @@ -518,12 +518,12 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { let hir::ItemKind::Impl(ref impl_) = it.kind else { return; }; - debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id); - if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) { + debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id); + if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) { check_impl_items_against_trait( tcx, it.span, - it.def_id.def_id, + it.owner_id.def_id, impl_trait_ref, &impl_.items, ); @@ -545,15 +545,15 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { fn_maybe_err(tcx, item.ident.span, abi); } hir::TraitItemKind::Type(.., Some(default)) => { - let assoc_item = tcx.associated_item(item.def_id); + let assoc_item = tcx.associated_item(item.owner_id); let trait_substs = - InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); + InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id()); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( tcx, assoc_item, assoc_item, default.span, - ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, + ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs }, ); } _ => {} @@ -561,16 +561,16 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::Struct => { - check_struct(tcx, id.def_id.def_id); + check_struct(tcx, id.owner_id.def_id); } DefKind::Union => { - check_union(tcx, id.def_id.def_id); + check_union(tcx, id.owner_id.def_id); } DefKind::OpaqueTy => { check_opaque(tcx, id); } DefKind::ImplTraitPlaceholder => { - let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id()); + let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id()); // Only check the validity of this opaque type if the function has a default body if let hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), @@ -581,8 +581,8 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::TyAlias => { - let pty_ty = tcx.type_of(id.def_id); - let generics = tcx.generics_of(id.def_id); + let pty_ty = tcx.type_of(id.owner_id); + let generics = tcx.generics_of(id.owner_id); check_type_params_are_used(tcx, &generics, pty_ty); } DefKind::ForeignMod => { @@ -604,7 +604,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } else { for item in items { - let def_id = item.id.def_id.def_id; + let def_id = item.id.owner_id.def_id; let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.params.len() - own_counts.lifetimes != 0 { @@ -659,7 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { // an error would be reported if this fails. - let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id()); + let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id()); } pub(super) fn check_specialization_validity<'tcx>( @@ -746,7 +746,7 @@ fn check_impl_items_against_trait<'tcx>( let trait_def = tcx.trait_def(impl_trait_ref.def_id); for impl_item in impl_item_refs { - let ty_impl_item = tcx.associated_item(impl_item.id.def_id); + let ty_impl_item = tcx.associated_item(impl_item.id.owner_id); let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id { tcx.associated_item(trait_item_id) } else { @@ -758,7 +758,7 @@ fn check_impl_items_against_trait<'tcx>( match impl_item_full.kind { hir::ImplItemKind::Const(..) => { let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( - impl_item.id.def_id.def_id, + impl_item.id.owner_id.def_id, ty_impl_item.trait_item_def_id.unwrap(), )); } @@ -1180,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L } } - if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant { + if tcx.adt_def(def_id).repr().int.is_none() { let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index e72f18012ab..32f66b06f83 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -597,7 +597,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let num_trait_substs = trait_to_impl_substs.len(); let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len(); let ty = tcx.fold_regions(ty, |region, _| { - let ty::ReFree(_) = region.kind() else { return region; }; + let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; }; let Some(ty::ReEarlyBound(e)) = map.get(®ion.into()).map(|r| r.expect_region().kind()) else { tcx diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 8be1cf04f8b..609095c9cea 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>( ) { let (own_counts, span) = match &it.kind { hir::ForeignItemKind::Fn(.., generics) => { - let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts(); + let own_counts = tcx.generics_of(it.owner_id.to_def_id()).own_counts(); (own_counts, generics.span) } _ => { @@ -57,7 +57,7 @@ fn equate_intrinsic_type<'tcx>( { let fty = tcx.mk_fn_ptr(sig); let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType); - require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty); + require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id)), fty); } } @@ -129,7 +129,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir /// and in `library/core/src/intrinsics.rs`. pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); - let intrinsic_id = it.def_id.to_def_id(); + let intrinsic_id = it.owner_id.to_def_id(); let intrinsic_name = tcx.item_name(intrinsic_id); let name_str = intrinsic_name.as_str(); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index a026f8033c8..17c4d0d482f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { // Type still may have region variables, but `Sized` does not depend // on those, so just erase them before querying. - if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) { + if ty.is_sized(self.tcx, self.param_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -128,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { let msg = "arguments for inline assembly must be copyable"; let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!("`{ty}` does not implement the Copy trait")); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 33ed3b96aa8..a2357500465 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -147,10 +147,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { /// the types first. #[instrument(skip(tcx), level = "debug")] fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; debug!( - ?item.def_id, + ?item.owner_id, item.name = ? tcx.def_path_str(def_id.to_def_id()) ); @@ -246,10 +246,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; debug!( - ?item.def_id, + ?item.owner_id, item.name = ? tcx.def_path_str(def_id.to_def_id()) ); @@ -263,7 +263,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { } fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { - let def_id = trait_item.def_id.def_id; + let def_id = trait_item.owner_id.def_id; let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -275,7 +275,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { let encl_trait_def_id = tcx.local_parent(def_id); let encl_trait = tcx.hir().expect_item(encl_trait_def_id); - let encl_trait_def_id = encl_trait.def_id.to_def_id(); + let encl_trait_def_id = encl_trait.owner_id.to_def_id(); let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { Some("fn") } else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() { @@ -348,7 +348,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe loop { let mut should_continue = false; for gat_item in associated_items { - let gat_def_id = gat_item.id.def_id; + let gat_def_id = gat_item.id.owner_id; let gat_item = tcx.associated_item(gat_def_id); // If this item is not an assoc ty, or has no substs, then it's not a GAT if gat_item.kind != ty::AssocKind::Type { @@ -365,7 +365,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe // constrains the GAT with individually. let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None; for item in associated_items { - let item_def_id = item.id.def_id; + let item_def_id = item.id.owner_id; // Skip our own GAT, since it does not constrain itself at all. if item_def_id == gat_def_id { continue; @@ -713,6 +713,10 @@ fn resolve_regions_with_wf_tys<'tcx>( add_constraints(&infcx, region_bound_pairs); + infcx.process_registered_region_obligations( + outlives_environment.region_bound_pairs(), + param_env, + ); let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); @@ -786,7 +790,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem let (trait_name, trait_def_id) = match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(..) => (item.ident, item.def_id), + hir::ItemKind::Trait(..) => (item.ident, item.owner_id), _ => return, }, _ => return, @@ -841,7 +845,7 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { _ => (None, impl_item.span), }; - check_associated_item(tcx, impl_item.def_id.def_id, span, method_sig); + check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -1041,11 +1045,11 @@ fn check_type_defn<'tcx, F>( ) where F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>, { - let _ = tcx.representability(item.def_id.def_id); + let _ = tcx.representability(item.owner_id.def_id); - enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { let variants = lookup_fields(wfcx); - let packed = tcx.adt_def(item.def_id).repr().packed(); + let packed = tcx.adt_def(item.owner_id).repr().packed(); for variant in &variants { // All field types must be well-formed. @@ -1069,7 +1073,7 @@ fn check_type_defn<'tcx, F>( // Just treat unresolved type expression as if it needs drop. true } else { - ty.needs_drop(tcx, tcx.param_env(item.def_id)) + ty.needs_drop(tcx, tcx.param_env(item.owner_id)) } } }; @@ -1117,15 +1121,15 @@ fn check_type_defn<'tcx, F>( } } - check_where_clauses(wfcx, item.span, item.def_id.def_id); + check_where_clauses(wfcx, item.span, item.owner_id.def_id); }); } #[instrument(skip(tcx, item))] fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { - debug!(?item.def_id); + debug!(?item.owner_id); - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; let trait_def = tcx.trait_def(def_id); if trait_def.is_marker || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) @@ -1236,13 +1240,13 @@ fn check_impl<'tcx>( ast_trait_ref: &Option<hir::TraitRef<'_>>, constness: hir::Constness, ) { - enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { match *ast_trait_ref { Some(ref ast_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap(); + let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap(); let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref); let trait_pred = ty::TraitPredicate { trait_ref, @@ -1264,7 +1268,7 @@ fn check_impl<'tcx>( wfcx.register_obligations(obligations); } None => { - let self_ty = tcx.type_of(item.def_id); + let self_ty = tcx.type_of(item.owner_id); let self_ty = wfcx.normalize( item.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), @@ -1278,7 +1282,7 @@ fn check_impl<'tcx>( } } - check_where_clauses(wfcx, item.span, item.def_id.def_id); + check_where_clauses(wfcx, item.span, item.owner_id.def_id); }); } @@ -1774,14 +1778,14 @@ fn check_variances_for_type_defn<'tcx>( item: &hir::Item<'tcx>, hir_generics: &hir::Generics<'_>, ) { - let ty = tcx.type_of(item.def_id); + let ty = tcx.type_of(item.owner_id); if tcx.has_error_field(ty) { return; } - let ty_predicates = tcx.predicates_of(item.def_id); + let ty_predicates = tcx.predicates_of(item.owner_id); assert_eq!(ty_predicates.parent, None); - let variances = tcx.variances_of(item.def_id); + let variances = tcx.variances_of(item.owner_id); let mut constrained_parameters: FxHashSet<_> = variances .iter() @@ -1794,7 +1798,7 @@ fn check_variances_for_type_defn<'tcx>( // Lazily calculated because it is only needed in case of an error. let explicitly_bounded_params = LazyCell::new(|| { - let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id()); + let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id()); hir_generics .predicates .iter() @@ -1915,10 +1919,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) { let items = tcx.hir_module_items(module); - items.par_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id)); - items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id)); + items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)); + items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)); } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 922833f8580..d0c31733481 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -1,5 +1,6 @@ use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unord::UnordSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -8,12 +9,12 @@ use rustc_session::lint; use rustc_span::{Span, Symbol}; pub fn check_crate(tcx: TyCtxt<'_>) { - let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default(); + let mut used_trait_imports: UnordSet<LocalDefId> = Default::default(); for item_def_id in tcx.hir().body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); - used_trait_imports.extend(imports.iter()); + used_trait_imports.extend(imports.items().copied()); } for &id in tcx.maybe_unused_trait_imports(()) { @@ -89,11 +90,11 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { let mut crates_to_lint = vec![]; for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) { + if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) { let item = tcx.hir().item(id); if let hir::ItemKind::ExternCrate(orig_name) = item.kind { crates_to_lint.push(ExternCrateToLint { - def_id: item.def_id.to_def_id(), + def_id: item.owner_id.to_def_id(), span: item.span, orig_name, warn_if_unused: !item.ident.as_str().starts_with('_'), diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 308ad5d5fc2..2890c149b3a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -58,7 +58,7 @@ const ADD_ATTR: &str = impl<'tcx> InherentCollect<'tcx> { fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId) { - let impl_def_id = item.def_id; + let impl_def_id = item.owner_id; if let Some(def_id) = def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and @@ -89,7 +89,7 @@ impl<'tcx> InherentCollect<'tcx> { for impl_item in items { if !self .tcx - .has_attr(impl_item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + .has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl) { struct_span_err!( self.tcx.sess, @@ -135,7 +135,7 @@ impl<'tcx> InherentCollect<'tcx> { for item in items { if !self .tcx - .has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + .has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl) { struct_span_err!( self.tcx.sess, @@ -177,7 +177,7 @@ impl<'tcx> InherentCollect<'tcx> { } fn check_item(&mut self, id: hir::ItemId) { - if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) { + if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) { return; } @@ -186,7 +186,7 @@ impl<'tcx> InherentCollect<'tcx> { return; }; - let self_ty = self.tcx.type_of(item.def_id); + let self_ty = self.tcx.type_of(item.owner_id); match *self_ty.kind() { ty::Adt(def, _) => { self.check_def_id(item, self_ty, def.did()); @@ -221,7 +221,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Never | ty::FnPtr(_) | ty::Tuple(..) => { - self.check_primitive_impl(item.def_id.def_id, self_ty, items, ty.span) + self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span) } ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => { let mut err = struct_span_err!( @@ -243,7 +243,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { - bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty); + bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty); } ty::Error(_) => {} } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 130eb8005b0..972769eb197 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -156,14 +156,14 @@ impl<'tcx> InherentOverlapChecker<'tcx> { } fn check_item(&mut self, id: hir::ItemId) { - let def_kind = self.tcx.def_kind(id.def_id); + let def_kind = self.tcx.def_kind(id.owner_id); if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) { return; } - let impls = self.tcx.inherent_impls(id.def_id); + let impls = self.tcx.inherent_impls(id.owner_id); - let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id()); + let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id()); let impls_items = impls .iter() diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1307f74f210..bb45c3823d8 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -101,7 +101,7 @@ fn do_orphan_check_impl<'tcx>( span_bug!(sp, "opaque type not found, but `has_opaque_types` is set") } - match traits::orphan_check(tcx, item.def_id.to_def_id()) { + match traits::orphan_check(tcx, item.owner_id.to_def_id()) { Ok(()) => {} Err(err) => emit_orphan_check_error( tcx, diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index e45fb5fe41c..a34815b45b3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,7 +13,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; - if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); @@ -26,6 +26,12 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "implementing the trait `{}` is not unsafe", trait_ref.print_only_trait_path() ) + .span_suggestion_verbose( + item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), + "remove `unsafe` from this trait implementation", + "", + rustc_errors::Applicability::MachineApplicable, + ) .emit(); } @@ -37,6 +43,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_only_trait_path() ) + .note(format!( + "the trait `{}` enforces invariants that the compiler can't check. \ + Review the trait documentation and make sure this implementation \ + upholds those invariants before adding the `unsafe` keyword", + trait_ref.print_only_trait_path() + )) + .span_suggestion_verbose( + item.span.shrink_to_lo(), + "add `unsafe` to this trait implementation", + "unsafe ", + rustc_errors::Applicability::MaybeIncorrect, + ) .emit(); } @@ -48,6 +66,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name ) + .note(format!( + "the trait `{}` enforces invariants that the compiler can't check. \ + Review the trait documentation and make sure this implementation \ + upholds those invariants before adding the `unsafe` keyword", + trait_ref.print_only_trait_path() + )) + .span_suggestion_verbose( + item.span.shrink_to_lo(), + "add `unsafe` to this trait implementation", + "unsafe ", + rustc_errors::Applicability::MaybeIncorrect, + ) .emit(); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 66ca7d7aa08..346d2e2fc4b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -571,7 +571,7 @@ fn get_new_lifetime_name<'tcx>( fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id()); - let def_id = item_id.def_id.def_id; + let def_id = item_id.owner_id.def_id; match it.kind { // These don't define types. @@ -583,11 +583,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::ForeignMod { items, .. } => { for item in items { let item = tcx.hir().foreign_item(item.id); - tcx.ensure().generics_of(item.def_id); - tcx.ensure().type_of(item.def_id); - tcx.ensure().predicates_of(item.def_id); + tcx.ensure().generics_of(item.owner_id); + tcx.ensure().type_of(item.owner_id); + tcx.ensure().predicates_of(item.owner_id); match item.kind { - hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id), + hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.owner_id), hir::ForeignItemKind::Static(..) => { let mut visitor = HirPlaceholderCollector::default(); visitor.visit_foreign_item(item); @@ -683,7 +683,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let trait_item = tcx.hir().trait_item(trait_item_id); - let def_id = trait_item_id.def_id; + let def_id = trait_item_id.owner_id; tcx.ensure().generics_of(def_id); match trait_item.kind { @@ -730,7 +730,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { - let def_id = impl_item_id.def_id; + let def_id = impl_item_id.owner_id; tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); @@ -1010,7 +1010,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { match item { Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { - if !tcx.impl_defaultness(item.id.def_id).has_value() { + if !tcx.impl_defaultness(item.id.owner_id).has_value() { tcx.sess .struct_span_err( item.span, @@ -1143,7 +1143,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { - // Do not try to inference the return type for a impl method coming from a trait + // Do not try to infer 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() @@ -1286,15 +1286,46 @@ fn infer_return_ty_for_fn_sig<'tcx>( 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 { + let item = tcx.hir().expect_item(def_id.expect_local()); + match item.kind { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); - <dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) + <dyn AstConv<'_>>::instantiate_mono_trait_ref( + &icx, + ast_trait_ref, + selfty, + check_impl_constness(tcx, impl_.constness, ast_trait_ref), + ) }), _ => bug!(), } } +fn check_impl_constness( + tcx: TyCtxt<'_>, + constness: hir::Constness, + ast_trait_ref: &hir::TraitRef<'_>, +) -> ty::BoundConstness { + match constness { + hir::Constness::Const => { + if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { + let trait_name = tcx.item_name(trait_def_id).to_string(); + tcx.sess.emit_err(errors::ConstImplForNonConstTrait { + trait_ref_span: ast_trait_ref.path.span, + trait_name, + local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()), + marking: (), + adding: (), + }); + ty::BoundConstness::NotConst + } else { + ty::BoundConstness::ConstIfConst + } + }, + hir::Constness::NotConst => ty::BoundConstness::NotConst, + } +} + fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(def_id.expect_local()); diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 707fd6c7527..c7777a94689 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -249,6 +249,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; + let mut next_index = || { + let prev = i; + i += 1; + prev as u32 + type_start + }; const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \ `struct`, `enum`, `type`, or `trait` definitions"; @@ -278,15 +283,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }; - let param_def = ty::GenericParamDef { - index: type_start + i as u32, + Some(ty::GenericParamDef { + index: next_index(), name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, kind, - }; - i += 1; - Some(param_def) + }) } GenericParamKind::Const { default, .. } => { if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() { @@ -297,15 +300,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { ); } - let param_def = ty::GenericParamDef { - index: type_start + i as u32, + Some(ty::GenericParamDef { + index: next_index(), name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, - }; - i += 1; - Some(param_def) + }) } })); @@ -323,8 +324,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { &["<closure_kind>", "<closure_signature>", "<upvars>"][..] }; - params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef { - index: type_start + i as u32, + params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { + index: next_index(), name: Symbol::intern(arg), def_id, pure_wrt_drop: false, @@ -337,7 +338,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { params.push(ty::GenericParamDef { - index: type_start, + index: next_index(), name: Symbol::intern("<const_ty>"), def_id, pure_wrt_drop: false, diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index c1214698cf7..3f263a6de24 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -331,8 +331,8 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime /// `resolve_lifetimes`. fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes { let item_id = item_for(tcx, def_id.def_id); - let local_def_id = item_id.def_id.def_id; - if item_id.def_id == def_id { + let local_def_id = item_id.owner_id.def_id; + if item_id.owner_id == def_id { let item = tcx.hir().item(item_id); match item.kind { hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id), @@ -557,11 +557,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // their owner, we can keep going until we find the Item that owns that. We then // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`. - for (_hir_id, node) in self.tcx.hir().parent_iter(item.def_id.into()) { + for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) { match node { hir::Node::Item(parent_item) => { let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes( - item_for(self.tcx, parent_item.def_id.def_id).def_id.def_id, + item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id, ); // We need to add *all* deps, since opaque tys may want them from *us* for (&owner, defs) in resolved_lifetimes.defs.iter() { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 32f359a8158..c29a645eb4a 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -319,7 +319,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty), - ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(*self_ty), + ItemKind::Impl(hir::Impl { self_ty, .. }) => { + match self_ty.find_self_aliases() { + spans if spans.len() > 0 => { + tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), }); + tcx.ty_error() + }, + _ => icx.to_ty(*self_ty), + } + }, ItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) @@ -635,24 +643,24 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - trace!(?it.def_id); - self.check(it.def_id.def_id); + trace!(?it.owner_id); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } } @@ -693,6 +701,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(tcx.local_parent(def_id).to_def_id()), + what: match tcx.hir().get(scope) { + _ if scope == hir::CRATE_HIR_ID => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", + Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl", + _ => "item", + }, }); return tcx.ty_error(); }; @@ -764,24 +778,24 @@ fn find_opaque_ty_constraints_for_rpit( intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - trace!(?it.def_id); + trace!(?it.owner_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id.def_id != self.def_id { - self.check(it.def_id.def_id); + if it.owner_id.def_id != self.def_id { + self.check(it.owner_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - trace!(?it.def_id); - self.check(it.def_id.def_id); + trace!(?it.owner_id); + self.check(it.owner_id.def_id); intravisit::walk_trait_item(self, it); } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9457da32ce6..d5b1a7ce1c2 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by `rustc_hir_analysis`. -use rustc_errors::IntoDiagnostic; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler}; +use rustc_errors::{IntoDiagnostic, MultiSpan}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -143,6 +143,7 @@ pub struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, pub name: Symbol, + pub what: &'static str, } pub struct MissingTypeParams { @@ -249,3 +250,33 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_impl_for_non_const_trait)] +pub struct ConstImplForNonConstTrait { + #[primary_span] + pub trait_ref_span: Span, + pub trait_name: String, + #[suggestion(applicability = "machine-applicable", code = "#[const_trait]")] + pub local_trait_span: Option<Span>, + #[note] + pub marking: (), + #[note(adding)] + pub adding: (), +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_bound_for_non_const_trait)] +pub struct ConstBoundForNonConstTrait { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_self_in_impl_self)] +pub struct SelfInImplSelf { + #[primary_span] + pub span: MultiSpan, + #[note] + pub note: (), +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index a84257b939c..136f6199911 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -55,10 +55,10 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); for id in module.items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - enforce_impl_params_are_constrained(tcx, id.def_id.def_id); + if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { + enforce_impl_params_are_constrained(tcx, id.owner_id.def_id); if min_specialization { - check_min_specialization(tcx, id.def_id.def_id); + check_min_specialization(tcx, id.owner_id.def_id); } } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dba505149de..525cd24190a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -381,7 +381,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { error = true; } if let hir::IsAsync::Async = sig.header.asyncness { - let span = tcx.def_span(it.def_id); + let span = tcx.def_span(it.owner_id); struct_span_err!( tcx.sess, span, diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 064a70107fe..90c6edb65e4 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -29,7 +29,7 @@ pub(super) fn infer_predicates<'tcx>( // Visit all the crates and infer predicates for id in tcx.hir().items() { - let item_did = id.def_id; + let item_did = id.owner_id; debug!("InferVisitor::visit_item(item={:?})", item_did); diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index eb0e1203405..fa2ac56593b 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -6,11 +6,11 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. - if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) { - let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id); + if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) { + let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id); struct_span_err!( tcx.sess, - tcx.def_span(id.def_id), + tcx.def_span(id.owner_id), E0640, "{:?}", inferred_outlives_of diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 2ba87db880b..83ed3e44b3d 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -6,9 +6,10 @@ pub fn test_variance(tcx: TyCtxt<'_>) { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. for id in tcx.hir().items() { - if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) { - let variances_of = tcx.variances_of(id.def_id); - struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit(); + if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) { + let variances_of = tcx.variances_of(id.owner_id); + struct_span_err!(tcx.sess, tcx.def_span(id.owner_id), E0208, "{:?}", variances_of) + .emit(); } } } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0e7576ecf8b..d1dab0540be 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -60,6 +60,8 @@ pub struct CastCheck<'tcx> { cast_ty: Ty<'tcx>, cast_span: Span, span: Span, + /// whether the cast is made in a const context or not. + pub constness: hir::Constness, } /// The kind of pointer and associated metadata (thin, length or vtable) - we @@ -210,9 +212,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { cast_ty: Ty<'tcx>, cast_span: Span, span: Span, + constness: hir::Constness, ) -> Result<CastCheck<'tcx>, ErrorGuaranteed> { let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span); - let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span }; + let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness }; // For better error messages, check for some obviously unsized // cases now. We do a more thorough check at the end, once @@ -866,7 +869,13 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), - (_, DynStar) | (DynStar, _) => bug!("should be handled by `try_coerce`"), + (_, DynStar) | (DynStar, _) => { + if fcx.tcx.features().dyn_star { + bug!("should be handled by `try_coerce`") + } else { + Err(CastError::IllegalCast) + } + } } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 2974ac97f23..16febfc46da 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -530,24 +530,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, hir_id: hir::HirId, ) -> Vec<AssocItem> { - let mut methods = - self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, hir_id); - methods.retain(|m| { - self.has_only_self_parameter(m) - && self - .tcx - // This special internal attribute is used to permit - // "identity-like" conversion methods to be suggested here. - // - // FIXME (#46459 and #46460): ideally - // `std::convert::Into::into` and `std::borrow:ToOwned` would - // also be `#[rustc_conversion_suggestion]`, if not for - // method-probing false-positives and -negatives (respectively). - // - // FIXME? Other potential candidate methods: `as_ref` and - // `as_mut`? - .has_attr(m.def_id, sym::rustc_conversion_suggestion) - }); + let methods = self.probe_for_return_type( + span, + probe::Mode::MethodCall, + expected, + checked_ty, + hir_id, + |m| { + self.has_only_self_parameter(m) + && self + .tcx + // This special internal attribute is used to permit + // "identity-like" conversion methods to be suggested here. + // + // FIXME (#46459 and #46460): ideally + // `std::convert::Into::into` and `std::borrow:ToOwned` would + // also be `#[rustc_conversion_suggestion]`, if not for + // method-probing false-positives and -negatives (respectively). + // + // FIXME? Other potential candidate methods: `as_ref` and + // `as_mut`? + .has_attr(m.def_id, sym::rustc_conversion_suggestion) + }, + ); methods } @@ -714,7 +719,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, checked_ty: Ty<'tcx>, expected: Ty<'tcx>, - ) -> Option<(Span, String, String, Applicability, bool /* verbose */)> { + ) -> Option<( + Span, + String, + String, + Applicability, + bool, /* verbose */ + bool, /* suggest `&` or `&mut` type annotation */ + )> { let sess = self.sess(); let sp = expr.span; @@ -746,6 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + false, )); } } @@ -760,6 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "b".to_string(), Applicability::MachineApplicable, true, + false, )); } } @@ -817,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg.2, Applicability::MachineApplicable, false, + false, )); } @@ -844,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&mut {sugg_expr}"), Applicability::MachineApplicable, false, + false, ), hir::Mutability::Not => ( sp, @@ -851,6 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{prefix}&{sugg_expr}"), Applicability::MachineApplicable, false, + false, ), }); } @@ -880,6 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true )); } return None; @@ -893,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { String::new(), Applicability::MachineApplicable, true, + true, )); } } @@ -959,6 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { src, applicability, true, + false, )); } } @@ -999,6 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable }, true, + false, )); } @@ -1050,6 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggestion, Applicability::MachineApplicable, true, + false, )); } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 41b00fda03e..9fde62a81a1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1272,7 +1272,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // Defer other checks until we're done type checking. let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); - match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) { + match cast::CastCheck::new( + self, + e, + t_expr, + t_cast, + t.span, + expr.span, + self.param_env.constness(), + ) { Ok(cast_check) => { debug!( "check_expr_cast: deferring cast from {:?} to {:?}: {:?}", diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 08a3cbccfb0..8e0fcb56c7f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -33,16 +33,27 @@ use rustc_span::{self, sym, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; use std::iter; +use std::mem; use std::ops::ControlFlow; use std::slice; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub(in super::super) fn check_casts(&self) { - let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut(); + pub(in super::super) fn check_casts(&mut self) { + // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors + // when writing to `self.param_env`. + let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut()); + debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len()); for cast in deferred_cast_checks.drain(..) { + let prev_env = self.param_env; + self.param_env = self.param_env.with_constness(cast.constness); + cast.check(self); + + self.param_env = prev_env; } + + *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks; } pub(in super::super) fn check_transmutes(&self) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index cd2e41aff0f..4db9c56f98f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let expr = expr.peel_blocks(); - if let Some((sp, msg, suggestion, applicability, verbose)) = + if let Some((sp, msg, suggestion, applicability, verbose, annotation)) = self.check_ref(expr, found, expected) { if verbose { @@ -335,9 +335,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_suggestion(sp, &msg, suggestion, applicability); } + if annotation { + let suggest_annotation = match expr.peel_drop_temps().kind { + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&", + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ", + _ => return true, + }; + let mut tuple_indexes = Vec::new(); + let mut expr_id = expr.hir_id; + for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) { + match node { + Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => { + tuple_indexes.push( + subs.iter() + .enumerate() + .find(|(_, sub_expr)| sub_expr.hir_id == expr_id) + .unwrap() + .0, + ); + expr_id = parent_id; + } + Node::Local(local) => { + if let Some(mut ty) = local.ty { + while let Some(index) = tuple_indexes.pop() { + match ty.kind { + TyKind::Tup(tys) => ty = &tys[index], + _ => return true, + } + } + let annotation_span = ty.span; + err.span_suggestion( + annotation_span.with_hi(annotation_span.lo()), + format!("alternatively, consider changing the type annotation"), + suggest_annotation, + Applicability::MaybeIncorrect, + ); + } + break; + } + _ => break, + } + } + } return true; - } else if self.suggest_else_fn_with_closure(err, expr, found, expected) - { + } else if self.suggest_else_fn_with_closure(err, expr, found, expected) { return true; } else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected)) && let ty::FnDef(def_id, ..) = &found.kind() diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index e862d577573..959c5486645 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ pub use inherited::{Inherited, InheritedBuilder}; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; use crate::gather_locals::GatherLocalsVisitor; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::unord::UnordSet; use rustc_errors::{struct_span_err, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -174,7 +174,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> { +fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> { &*tcx.typeck(def_id).used_trait_imports } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74cf2ac32aa..28aa2302f88 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// would result in an error (basically, the same criteria we /// would use to decide if a method is a plausible fit for /// ambiguity purposes). - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, candidate_filter))] pub fn probe_for_return_type( &self, span: Span, @@ -260,6 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type: Ty<'tcx>, self_ty: Ty<'tcx>, scope_expr_id: hir::HirId, + candidate_filter: impl Fn(&ty::AssocItem) -> bool, ) -> Vec<ty::AssocItem> { let method_names = self .probe_op( @@ -271,7 +272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty, scope_expr_id, ProbeScope::AllTraits, - |probe_cx| Ok(probe_cx.candidate_method_names()), + |probe_cx| Ok(probe_cx.candidate_method_names(candidate_filter)), ) .unwrap_or_default(); method_names @@ -966,12 +967,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - fn candidate_method_names(&self) -> Vec<Ident> { + fn candidate_method_names( + &self, + candidate_filter: impl Fn(&ty::AssocItem) -> bool, + ) -> Vec<Ident> { let mut set = FxHashSet::default(); let mut names: Vec<_> = self .inherent_candidates .iter() .chain(&self.extension_candidates) + .filter(|candidate| candidate_filter(&candidate.item)) .filter(|candidate| { if let Some(return_ty) = self.return_type { self.matches_return_type(&candidate.item, None, return_ty) @@ -1689,7 +1694,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); - let method_names = pcx.candidate_method_names(); + let method_names = pcx.candidate_method_names(|_| true); pcx.allow_similar_names = false; let applicable_close_candidates: Vec<ty::AssocItem> = method_names .iter() diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f4351bfa84a..6c21ed902d0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -106,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let report_candidates = |span: Span, err: &mut Diagnostic, - mut sources: Vec<CandidateSource>, + sources: &mut Vec<CandidateSource>, sugg_span: Span| { sources.sort(); sources.dedup(); @@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { MethodError::NoMatch(NoMatchData { - static_candidates: static_sources, + static_candidates: mut static_sources, unsatisfied_predicates, out_of_scope_traits, lev_candidate, @@ -422,9 +422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help(&format!("try with `{}::{}`", ty_str, item_name,)); } - report_candidates(span, &mut err, static_sources, sugg_span); + report_candidates(span, &mut err, &mut static_sources, sugg_span); } else if static_sources.len() > 1 { - report_candidates(span, &mut err, static_sources, sugg_span); + report_candidates(span, &mut err, &mut static_sources, sugg_span); } let mut bound_spans = vec![]; @@ -1007,6 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, out_of_scope_traits, &unsatisfied_predicates, + &static_sources, unsatisfied_bounds, ); } @@ -1079,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(err); } - MethodError::Ambiguity(sources) => { + MethodError::Ambiguity(mut sources) => { let mut err = struct_span_err!( self.sess(), item_name.span, @@ -1088,7 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(item_name.span, format!("multiple `{}` found", item_name)); - report_candidates(span, &mut err, sources, sugg_span); + report_candidates(span, &mut err, &mut sources, sugg_span); err.emit(); } @@ -2015,6 +2016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, )], + static_candidates: &[CandidateSource], unsatisfied_bounds: bool, ) { let mut alt_rcvr_sugg = false; @@ -2129,6 +2131,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => true, }) .filter(|info| { + // Static candidates are already implemented, and known not to work + // Do not suggest them again + static_candidates.iter().all(|sc| match *sc { + CandidateSource::Trait(def_id) => def_id != info.def_id, + CandidateSource::Impl(def_id) => { + self.tcx.trait_id_of_impl(def_id) != Some(info.def_id) + } + }) + }) + .filter(|info| { // We approximate the coherence rules to only suggest // traits that are legal to implement by requiring that // either the type or trait is local. Multi-dispatch means diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 9c19f16a496..79e2d371ed3 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.def_id.def_id); + dirty_clean_visitor.check_item(id.owner_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 608b5cc8756..a299a3e578d 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -16,8 +16,8 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::traits::query::{Fallible, NoSolution}; -use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{PredicateObligations, TraitEngine}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; @@ -509,7 +509,7 @@ impl<'tcx> InferCtxt<'tcx> { for &(a, b) in &query_response.value.opaque_types { let a = substitute_value(self.tcx, &result_subst, a); let b = substitute_value(self.tcx, &result_subst, b); - obligations.extend(self.handle_opaque_type(a, b, true, cause, param_env)?.obligations); + obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations); } Ok(InferOk { value: result_subst, obligations }) @@ -632,7 +632,7 @@ impl<'tcx> InferCtxt<'tcx> { /// creates query region constraints. pub fn make_query_region_constraints<'tcx>( tcx: TyCtxt<'tcx>, - outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory)>, + outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>, region_constraints: &RegionConstraintData<'tcx>, ) -> QueryRegionConstraints<'tcx> { let RegionConstraintData { constraints, verifys, givens, member_constraints } = @@ -741,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { true } - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: PredicateObligations<'tcx>, ) -> Result<(), TypeError<'tcx>> { - self.obligations.extend( - self.infcx - .handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)? - .obligations, - ); + self.obligations.extend(obligations); Ok(()) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 6bb736687d6..9bf755d7fcd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -286,8 +286,8 @@ pub fn suggest_new_region_bound( ) { debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; + let consider = "consider changing"; + let declare = "to declare that"; let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); let explicit_static = arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg)); @@ -305,6 +305,10 @@ pub fn suggest_new_region_bound( return; }; + // Get the identity type for this RPIT + let did = item_id.owner_id.to_def_id(); + let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + if let Some(span) = opaque .bounds .iter() @@ -321,7 +325,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, - &format!("{} `impl Trait`'s {}", consider, explicit_static), + &format!("{consider} `{ty}`'s {explicit_static}"), &lifetime_name, Applicability::MaybeIncorrect, ); @@ -351,12 +355,7 @@ pub fn suggest_new_region_bound( } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), + &format!("{declare} `{ty}` {captures}, {explicit}",), &plus_lt, Applicability::MaybeIncorrect, ); @@ -367,7 +366,7 @@ pub fn suggest_new_region_bound( err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), &format!( - "{declare} trait object {captures}, {explicit}", + "{declare} the trait object {captures}, {explicit}", declare = declare, captures = captures, explicit = explicit, @@ -384,7 +383,7 @@ pub fn suggest_new_region_bound( if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( lt.span, - &format!("{} trait object's {}", consider, explicit_static), + &format!("{} the trait object's {}", consider, explicit_static), &lifetime_name, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2732c92ecd3..ffb020398b8 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -425,7 +425,7 @@ pub enum SubregionOrigin<'tcx> { static_assert_size!(SubregionOrigin<'_>, 32); impl<'tcx> SubregionOrigin<'tcx> { - pub fn to_constraint_category(&self) -> ConstraintCategory { + pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self { Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(), Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span), @@ -1469,7 +1469,12 @@ impl<'tcx> InferCtxt<'tcx> { * except during the writeback phase. */ - resolve::fully_resolve(self, value) + let value = resolve::fully_resolve(self, value); + assert!( + value.as_ref().map_or(true, |value| !value.needs_infer()), + "`{value:?}` is not fully resolved" + ); + value } pub fn replace_bound_vars_with_fresh_vars<T>( diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 7c186ae9470..600f94f095e 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -25,7 +25,9 @@ use crate::infer::combine::ConstEquateRelation; use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; +use crate::traits::PredicateObligation; use rustc_data_structures::fx::FxHashMap; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -91,11 +93,9 @@ pub trait TypeRelatingDelegate<'tcx> { ); fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); - fn register_opaque_type( + fn register_opaque_type_obligations( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, - a_is_expected: bool, + obligations: Vec<PredicateObligation<'tcx>>, ) -> Result<(), TypeError<'tcx>>; /// Creates a new universe index. Used when instantiating placeholders. @@ -414,7 +414,12 @@ where (_, &ty::Opaque(..)) => (generalize(a, true)?, b), _ => unreachable!(), }; - self.delegate.register_opaque_type(a, b, true)?; + let cause = ObligationCause::dummy_with_span(self.delegate.span()); + let obligations = self + .infcx + .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())? + .obligations; + self.delegate.register_opaque_type_obligations(obligations)?; trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); Ok(a) } @@ -592,7 +597,7 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { - infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| { + infcx.super_combine_tys(self, a, b).or_else(|err| { self.tcx().sess.delay_span_bug( self.delegate.span(), "failure to relate an opaque to itself should result in an error later on", diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 0a4ecc4c033..a982f11f718 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -103,7 +103,7 @@ impl<'tcx> InferCtxt<'tcx> { return Ok(InferOk { value: (), obligations: vec![] }); } let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; - let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { + let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { ty::Opaque(def_id, substs) if def_id.is_local() => { let def_id = def_id.expect_local(); let origin = match self.defining_use_anchor { @@ -169,13 +169,14 @@ impl<'tcx> InferCtxt<'tcx> { param_env, b, origin, + a_is_expected, )) } _ => None, }; - if let Some(res) = process(a, b) { + if let Some(res) = process(a, b, true) { res - } else if let Some(res) = process(b, a) { + } else if let Some(res) = process(b, a, false) { res } else { let (a, b) = self.resolve_vars_if_possible((a, b)); @@ -514,13 +515,14 @@ impl UseKind { impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self), level = "debug")] - pub fn register_hidden_type( + fn register_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, origin: hir::OpaqueTyOrigin, + a_is_expected: bool, ) -> InferResult<'tcx, ()> { let tcx = self.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; @@ -539,7 +541,8 @@ impl<'tcx> InferCtxt<'tcx> { origin, ); if let Some(prev) = prev { - obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations; + obligations = + self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations; } let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5ebf80b7b74..6ca884799aa 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -210,7 +210,7 @@ pub trait TypeOutlivesDelegate<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - constraint_category: ConstraintCategory, + constraint_category: ConstraintCategory<'tcx>, ); fn push_verify( @@ -259,7 +259,7 @@ where origin: infer::SubregionOrigin<'tcx>, ty: Ty<'tcx>, region: ty::Region<'tcx>, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { assert!(!ty.has_escaping_bound_vars()); @@ -273,7 +273,7 @@ where origin: infer::SubregionOrigin<'tcx>, components: &[Component<'tcx>], region: ty::Region<'tcx>, - category: ConstraintCategory, + category: ConstraintCategory<'tcx>, ) { for component in components.iter() { let origin = origin.clone(); @@ -529,7 +529,7 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> { origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, - _constraint_category: ConstraintCategory, + _constraint_category: ConstraintCategory<'tcx>, ) { self.sub_regions(origin, a, b) } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index a4b55dfa691..97354ba5d1b 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -2,9 +2,7 @@ use super::combine::{CombineFields, RelationDir}; use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; -use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; @@ -130,39 +128,18 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if self.fields.define_opaque_types && did.is_local() => { - let mut generalize = |ty, ty_is_expected| { - let var = infcx.next_ty_var_id_in_universe( - TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: self.fields.trace.cause.span, - }, - ty::UniverseIndex::ROOT, - ); - self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?; - Ok(infcx.tcx.mk_ty_var(var)) - }; - let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) }; - let (ga, gb) = match (a.kind(), b.kind()) { - (&ty::Opaque(..), _) => (a, generalize(b, true)?), - (_, &ty::Opaque(..)) => (generalize(a, false)?, b), - _ => unreachable!(), - }; self.fields.obligations.extend( infcx - .handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env()) - // Don't leak any generalized type variables out of this - // subtyping relation in the case of a type error. - .map_err(|err| { - let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb)); - if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb { - TypeError::Sorts(ExpectedFound { expected: a, found: b }) - } else { - err - } - })? + .handle_opaque_type( + a, + b, + self.a_is_expected, + &self.fields.trace.cause, + self.param_env(), + )? .obligations, ); - Ok(ga) + Ok(a) } // Optimization of GeneratorWitness relation since we know that all // free regions are replaced with bound regions during construction. diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a47c3e3253e..7f1d21bf1d8 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::StableCrateId; -use rustc_hir::definitions::Definitions; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; @@ -30,7 +29,7 @@ use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn}; +use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -135,10 +134,7 @@ mod boxed_resolver { f((&mut *resolver).as_mut().unwrap()) } - pub fn to_resolver_outputs( - resolver: Rc<RefCell<BoxedResolver>>, - ) -> (Definitions, Box<CrateStoreDyn>, ty::ResolverOutputs, ty::ResolverAstLowering) - { + pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs { match Rc::try_unwrap(resolver) { Ok(resolver) => { let mut resolver = resolver.into_inner(); @@ -788,8 +784,7 @@ pub fn create_global_ctxt<'tcx>( // incr. comp. yet. dep_graph.assert_ignored(); - let (definitions, cstore, resolver_outputs, resolver_for_lowering) = - BoxedResolver::to_resolver_outputs(resolver); + let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let sess = &compiler.session(); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -816,10 +811,7 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - definitions, - cstore, resolver_outputs, - resolver_for_lowering, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), @@ -935,7 +927,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().privacy_access_levels(()); + tcx.ensure().effective_visibilities(()); parallel!( { diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 2b1b931b732..4c236c693d0 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -9,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { for id in tcx.hir().items() { let attrs = finder.tcx.hir().attrs(id.hir_id()); if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.def_id.def_id); + finder.decls = Some(id.owner_id.def_id); } } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index c71e6ffe34d..51515976e4e 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -57,29 +57,42 @@ pub enum TokenKind { // Multi-char tokens: /// "// comment" LineComment { doc_style: Option<DocStyle> }, + /// `/* block comment */` /// - /// Block comments can be recursive, so the sequence like `/* /* */` + /// Block comments can be recursive, so a sequence like `/* /* */` /// will not be considered terminated and will result in a parsing error. BlockComment { doc_style: Option<DocStyle>, terminated: bool }, - /// Any whitespace characters sequence. + + /// Any whitespace character sequence. Whitespace, + /// "ident" or "continue" - /// At this step keywords are also considered identifiers. + /// + /// At this step, keywords are also considered identifiers. Ident, + /// Like the above, but containing invalid unicode codepoints. InvalidIdent, + /// "r#ident" RawIdent, - /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the + + /// An unknown prefix, like `foo#`, `foo'`, `foo"`. + /// + /// Note that only the /// prefix (`foo`) is included in the token, not the separator (which is /// lexed as its own distinct token). In Rust 2021 and later, reserved /// prefixes are reported as errors; in earlier editions, they result in a /// (allowed by default) lint, and are treated as regular identifier /// tokens. UnknownPrefix, - /// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details. + + /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`. + /// + /// See [LiteralKind] for more details. Literal { kind: LiteralKind, suffix_start: u32 }, + /// "'a" Lifetime { starts_with_number: bool }, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 53c49105134..d425adf47f0 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers { | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id)) + self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id)) } _ => (), } @@ -563,7 +563,7 @@ impl MissingDoc { // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). if def_id != CRATE_DEF_ID { - if !cx.access_levels.is_exported(def_id) { + if !cx.effective_visibilities.is_exported(def_id) { return; } } @@ -606,9 +606,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { match it.kind { hir::ItemKind::Trait(..) => { // Issue #11592: traits are always considered exported, even when private. - if cx.tcx.visibility(it.def_id) + if cx.tcx.visibility(it.owner_id) == ty::Visibility::Restricted( - cx.tcx.parent_module_from_def_id(it.def_id.def_id).to_def_id(), + cx.tcx.parent_module_from_def_id(it.owner_id.def_id).to_def_id(), ) { return; @@ -627,15 +627,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { _ => return, }; - let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id.def_id, article, desc); + self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); + let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id.def_id, article, desc); + self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -662,13 +662,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } } - let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { - let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id.def_id, article, desc); + let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id()); + self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { @@ -721,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } let (def, ty) = match item.kind { @@ -729,21 +729,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Union(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemKind::Enum(_, ref ast_generics) => { if !ast_generics.params.is_empty() { return; } - let def = cx.tcx.adt_def(item.def_id); + let def = cx.tcx.adt_def(item.owner_id); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } _ => return, @@ -752,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let param_env = ty::ParamEnv::empty(); - if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) { + if ty.is_copy_modulo_regions(cx.tcx, param_env) { return; } if can_type_implement_copy( @@ -814,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id.def_id) { + if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { return; } @@ -841,7 +841,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { debug!("{:?}", self.impling_types); } - if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) { + if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) { cx.struct_span_lint( MISSING_DEBUG_IMPLEMENTATIONS, item.span, @@ -1226,7 +1226,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { check_no_mangle_on_generic_fn( no_mangle_attr, Some(generics), - cx.tcx.hir().get_generics(it.id.def_id.def_id).unwrap(), + cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(), it.span, ); } @@ -1385,7 +1385,8 @@ impl UnreachablePub { exportable: bool, ) { let mut applicability = Applicability::MachineApplicable; - if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) { + if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id) + { if vis_span.from_expansion() { applicability = Applicability::MaybeIncorrect; } @@ -1414,11 +1415,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id.def_id, item.vis_span, true); + self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint(cx, "item", foreign_item.def_id.def_id, foreign_item.vis_span, true); + self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { @@ -1428,8 +1429,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // 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.def_id, impl_item.vis_span, false); + if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() { + self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false); } } } @@ -1638,7 +1639,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { use rustc_middle::ty::PredicateKind::*; if cx.tcx.features().trivial_bounds { - let predicates = cx.tcx.predicates_of(item.def_id); + let predicates = cx.tcx.predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { Trait(..) => "trait", @@ -1881,7 +1882,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { if let hir::ItemKind::Mod(..) = it.kind { } else { self.items_nameable = false; - self.boundary = Some(it.def_id); + self.boundary = Some(it.owner_id); } return; } @@ -1898,7 +1899,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems { } fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) { - if !self.items_nameable && self.boundary == Some(it.def_id) { + if !self.items_nameable && self.boundary == Some(it.owner_id) { self.items_nameable = true; } } @@ -2164,7 +2165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; - let def_id = item.def_id.def_id; + let def_id = item.owner_id.def_id; if let hir::ItemKind::Struct(_, ref hir_generics) | hir::ItemKind::Enum(_, ref hir_generics) | hir::ItemKind::Union(_, ref hir_generics) = item.kind @@ -2743,7 +2744,7 @@ impl ClashingExternDeclarations { /// Insert a new foreign item into the seen set. If a symbol with the same name already exists /// for the item, return its HirId without updating the set. fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> { - let did = fi.def_id.to_def_id(); + let did = fi.owner_id.to_def_id(); let instance = Instance::new(did, ty::List::identity_for_item(tcx, did)); let name = Symbol::intern(tcx.symbol_name(instance).name); if let Some(&hir_id) = self.seen_decls.get(&name) { @@ -2761,14 +2762,14 @@ impl ClashingExternDeclarations { /// symbol's name. fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName { if let Some((overridden_link_name, overridden_link_name_span)) = - tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| { + tcx.codegen_fn_attrs(fi.owner_id).link_name.map(|overridden_link_name| { // FIXME: Instead of searching through the attributes again to get span // information, we could have codegen_fn_attrs also give span information back for // where the attribute was defined. However, until this is found to be a // bottleneck, this does just fine. ( overridden_link_name, - tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span, + tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span, ) }) { @@ -2985,10 +2986,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { let tcx = cx.tcx; if let Some(existing_hid) = self.insert(tcx, this_fi) { let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid)); - let this_decl_ty = tcx.type_of(this_fi.def_id); + let this_decl_ty = tcx.type_of(this_fi.owner_id); debug!( "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}", - existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty + existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty ); // Check that the declarations match. if !Self::structurally_same_type( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 63a11877333..cec0003ffea 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -31,7 +31,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -542,7 +542,7 @@ pub struct LateContext<'tcx> { pub param_env: ty::ParamEnv<'tcx>, /// Items accessible from the crate being checked. - pub access_levels: &'tcx AccessLevels, + pub effective_visibilities: &'tcx EffectiveVisibilities, /// The store of registered lints and the lint levels. pub lint_store: &'tcx LintStore, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index d4e19ef6b22..303fcb1a1d1 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -338,14 +338,14 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( module_def_id: LocalDefId, pass: T, ) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - access_levels, + effective_visibilities, lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id), generics: None, @@ -386,14 +386,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( } fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let context = LateContext { tcx, enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - access_levels, + effective_visibilities, lint_store: unerased_lint_store(tcx), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index fee6e080c4f..5288fc542d7 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -212,7 +212,7 @@ macro_rules! late_lint_mod_passes { TypeLimits: TypeLimits::new(), NonSnakeCase: NonSnakeCase, InvalidNoMangleItems: InvalidNoMangleItems, - // Depends on access levels + // Depends on effective visibilities UnreachablePub: UnreachablePub, ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, InvalidValue: InvalidValue, diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 7f6f4a0abb4..00bf287ba6b 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -61,7 +61,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; }; - let def_id = item.def_id.def_id.to_def_id(); + let def_id = item.owner_id.def_id.to_def_id(); let infcx = &cx.tcx.infer_ctxt().build(); // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index a118dda8b40..f22f38aa2ce 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { use rustc_middle::ty::PredicateKind::*; - let predicates = cx.tcx.explicit_predicates_of(item.def_id); + let predicates = cx.tcx.explicit_predicates_of(item.owner_id); for &(predicate, span) in predicates.predicates { let Trait(trait_predicate) = predicate.kind().skip_binder() else { continue diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c99bb2790f..37caab2da0f 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_span::source_map; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_span::{Span, Symbol}; use rustc_target::abi::{Abi, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; @@ -931,7 +931,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match *ty.kind() { ty::Adt(def, substs) => { if def.is_box() && matches!(self.mode, CItemKind::Definition) { - if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) { + if ty.boxed_ty().is_sized(tcx, self.cx.param_env) { return FfiSafe; } else { return FfiUnsafe { @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) if { matches!(self.mode, CItemKind::Definition) - && ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env) + && ty.is_sized(self.cx.tcx, self.cx.param_env) } => { FfiSafe @@ -1360,7 +1360,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { - let t = cx.tcx.type_of(it.def_id); + let t = cx.tcx.type_of(it.owner_id); let ty = cx.tcx.erase_regions(t); let Ok(layout) = cx.layout_of(ty) else { return }; let Variants::Multiple { diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 879a3b660b4..18d37d95a83 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -69,7 +69,9 @@ extern "C" void LLVMInitializePasses() { initializeAnalysis(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); +#if LLVM_VERSION_LT(16, 0) initializeInstrumentation(Registry); +#endif initializeTarget(Registry); } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 9f7d2661a3e..3ea83fd09c7 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -454,7 +454,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestion_with_style( + #diag.span_suggestions_with_style( #span_field, rustc_errors::fluent::#slug, #code_field, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index d1acb713842..fa0ca5a5242 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -11,9 +11,11 @@ use crate::diagnostics::utils::{ }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; +use super::utils::{build_suggestion_code, AllowMultipleAlternatives}; + /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDeriveBuilder { diag: syn::Ident, @@ -414,15 +416,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else { - throw_invalid_nested_attr!(attr, &nested_attr); - }; - match nested_name { "code" => { - let formatted_str = self.build_format(&value.value(), value.span()); let code_field = new_code_ident(); - code.set_once((code_field, formatted_str), span); + let formatting_init = build_suggestion_code( + &code_field, + meta, + self, + AllowMultipleAlternatives::No, + ); + code.set_once((code_field, formatting_init), span); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") @@ -430,14 +433,14 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - let Some((code_field, formatted_str)) = code.value() else { + let Some((code_field, formatting_init)) = code.value() else { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); return Ok(quote! {}); }; let binding = info.binding; - self.formatting_init.extend(quote! { let #code_field = #formatted_str; }); + self.formatting_init.extend(formatting_init); let code_field = if clone_suggestion_code { quote! { #code_field.clone() } } else { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 61d5007fc30..374c795d0a6 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -2,7 +2,7 @@ use crate::diagnostics::error::{ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use proc_macro::Span; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, ToTokens}; use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; @@ -395,6 +395,82 @@ pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<Stri fields_map } +#[derive(Copy, Clone, Debug)] +pub(super) enum AllowMultipleAlternatives { + No, + Yes, +} + +/// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or +/// `#[suggestion*(code("foo", "bar"))]` attribute field +pub(super) fn build_suggestion_code( + code_field: &Ident, + meta: &Meta, + fields: &impl HasFieldMap, + allow_multiple: AllowMultipleAlternatives, +) -> TokenStream { + let values = match meta { + // `code = "foo"` + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s], + // `code("foo", "bar")` + Meta::List(MetaList { nested, .. }) => { + if let AllowMultipleAlternatives::No = allow_multiple { + span_err( + meta.span().unwrap(), + "expected exactly one string literal for `code = ...`", + ) + .emit(); + vec![] + } else if nested.is_empty() { + span_err( + meta.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } else { + nested + .into_iter() + .filter_map(|item| { + if let NestedMeta::Lit(syn::Lit::Str(s)) = item { + Some(s) + } else { + span_err( + item.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + None + } + }) + .collect() + } + } + _ => { + span_err( + meta.span().unwrap(), + r#"`code = "..."`/`code(...)` must contain only string literals"#, + ) + .emit(); + vec![] + } + }; + + if let AllowMultipleAlternatives::Yes = allow_multiple { + let formatted_strings: Vec<_> = values + .into_iter() + .map(|value| fields.build_format(&value.value(), value.span())) + .collect(); + quote! { let #code_field = [#(#formatted_strings),*].into_iter(); } + } else if let [value] = values.as_slice() { + let formatted_str = fields.build_format(&value.value(), value.span()); + quote! { let #code_field = #formatted_str; } + } else { + // error handled previously + quote! { let #code_field = String::new(); } + } +} + /// Possible styles for suggestion subdiagnostics. #[derive(Clone, Copy)] pub(super) enum SuggestionKind { @@ -571,21 +647,23 @@ impl SubdiagnosticKind { let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + let string_value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("a diagnostic slug must be the first argument to the attribute") }), - _ => { - invalid_nested_attr(attr, &nested_attr).emit(); - continue; - } + _ => None, }; match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { - let formatted_str = fields.build_format(&value.value(), value.span()); - let code_init = quote! { let #code_field = #formatted_str; }; + let code_init = build_suggestion_code( + code_field, + meta, + fields, + AllowMultipleAlternatives::Yes, + ); code.set_once(code_init, span); } ( @@ -593,6 +671,11 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { ref mut applicability, .. } | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { + let Some(value) = string_value else { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + }; + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { span_err(span, "invalid applicability").emit(); Applicability::Unspecified @@ -623,7 +706,7 @@ impl SubdiagnosticKind { init } else { span_err(span, "suggestion without `code = \"...\"`").emit(); - quote! { let #code_field: String = unreachable!(); } + quote! { let #code_field = std::iter::empty(); } }; } SubdiagnosticKind::Label @@ -644,7 +727,7 @@ impl quote::IdentFragment for SubdiagnosticKind { SubdiagnosticKind::Note => write!(f, "note"), SubdiagnosticKind::Help => write!(f, "help"), SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"), SubdiagnosticKind::MultipartSuggestion { .. } => { write!(f, "multipart_suggestion_with_style") } diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 2ca4cd17fdf..d1c2f3104d0 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -6,13 +6,13 @@ use rustc_session::cstore::ForeignModule; pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> { let mut modules = Vec::new(); for id in tcx.hir().items() { - if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) { continue; } let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { - let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect(); - modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() }); + let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect(); + modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() }); } } modules diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 676c67bad82..20a2e78299a 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -98,7 +98,7 @@ struct Collector<'tcx> { impl<'tcx> Collector<'tcx> { fn process_item(&mut self, id: rustc_hir::ItemId) { - if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) { + if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) { return; } @@ -372,17 +372,17 @@ impl<'tcx> Collector<'tcx> { } _ => { for child_item in foreign_mod_items { - if self.tcx.def_kind(child_item.id.def_id).has_codegen_attrs() + if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs() && self .tcx - .codegen_fn_attrs(child_item.id.def_id) + .codegen_fn_attrs(child_item.id.owner_id) .link_ordinal .is_some() { let link_ordinal_attr = self .tcx .hir() - .attrs(child_item.id.def_id.into()) + .attrs(child_item.id.owner_id.into()) .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); @@ -402,7 +402,7 @@ impl<'tcx> Collector<'tcx> { filename, kind, cfg, - foreign_module: Some(it.def_id.to_def_id()), + foreign_module: Some(it.owner_id.to_def_id()), wasm_import_module: wasm_import_module.map(|(name, _)| name), verbatim, dll_imports, @@ -505,7 +505,7 @@ impl<'tcx> Collector<'tcx> { fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions( self.tcx - .type_of(item.id.def_id) + .type_of(item.id.owner_id) .fn_sig(self.tcx) .inputs() .map_bound(|slice| self.tcx.mk_type_list(slice.iter())), @@ -557,7 +557,7 @@ impl<'tcx> Collector<'tcx> { } }; - let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.def_id); + let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id); let import_name_type = codegen_fn_attrs .link_ordinal .map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord))); @@ -567,7 +567,7 @@ impl<'tcx> Collector<'tcx> { import_name_type, calling_convention, span: item.span, - is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(), + is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(), } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 830417eea1a..691e3d0f8f9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> { - self.def_key(item_index).disambiguated_data.data.get_opt_name() + let def_key = self.def_key(item_index); + def_key.disambiguated_data.data.get_opt_name().or_else(|| { + if def_key.disambiguated_data.data == DefPathData::Ctor { + let parent_index = def_key.parent.expect("no parent for a constructor"); + self.def_key(parent_index).disambiguated_data.data.get_opt_name() + } else { + None + } + }) } fn item_name(self, item_index: DefIndex) -> Symbol { @@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .get(self, item_id) .unwrap_or_else(LazyArray::empty) .decode(self) - .map(|index| self.get_variant(&self.def_kind(index), index, did)) + .filter_map(|index| { + let kind = self.def_kind(index); + match kind { + DefKind::Ctor(..) => None, + _ => Some(self.get_variant(&kind, index, did)), + } + }) .collect() } else { std::iter::once(self.get_variant(&kind, item_id, did)).collect() @@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { callback(ModChild { ident, res, vis, span, macro_rules }); - // For non-re-export structs and variants add their constructors to children. - // Re-export lists automatically contain constructors when necessary. - match kind { - DefKind::Struct => { - if let Some((ctor_def_id, ctor_kind)) = - self.get_ctor_def_id_and_kind(child_index) - { - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); - let vis = self.get_visibility(ctor_def_id.index); - callback(ModChild { - ident, - res: ctor_res, - vis, - span, - macro_rules: false, - }); - } - } - DefKind::Variant => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let (ctor_def_id, ctor_kind) = self - .get_ctor_def_id_and_kind(child_index) - .unwrap_or((def_id, CtorKind::Fictive)); - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis.is_public() { - // For non-exhaustive variants lower the constructor visibility to - // within the crate. We only need this for fictive constructors, - // for other constructors correct visibilities - // were already encoded in metadata. - let mut attrs = self.get_item_attrs(def_id.index, sess); - if attrs.any(|item| item.has_name(sym::non_exhaustive)) { - let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); - vis = ty::Visibility::Restricted(crate_def_id); - } + // For non-reexport variants add their fictive constructors to children. + // Braced variants, unlike structs, generate unusable names in value namespace, + // they are reserved for possible future use. It's ok to use the variant's id as + // a ctor id since an error will be reported on any use of such resolution anyway. + // Reexport lists automatically contain such constructors when necessary. + if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none() + { + let ctor_res = + Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id); + let mut vis = vis; + if vis.is_public() { + // For non-exhaustive variants lower the constructor visibility to + // within the crate. We only need this for fictive constructors, + // for other constructors correct visibilities + // were already encoded in metadata. + let mut attrs = self.get_item_attrs(def_id.index, sess); + if attrs.any(|item| item.has_name(sym::non_exhaustive)) { + vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX)); } - callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } - _ => {} + callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c019211a948..049514ec7b2 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -787,9 +787,8 @@ fn should_encode_attr( } else if attr.doc_str().is_some() { // We keep all public doc comments because they might be "imported" into downstream crates // if they use `#[doc(inline)]` to copy an item's documentation into their own. - *is_def_id_public.get_or_insert_with(|| { - tcx.privacy_access_levels(()).get_effective_vis(def_id).is_some() - }) + *is_def_id_public + .get_or_insert_with(|| tcx.effective_visibilities(()).effective_vis(def_id).is_some()) } else if attr.has_name(sym::doc) { // If this is a `doc` attribute, and it's marked `inline` (as in `#[doc(inline)]`), we can // remove it. It won't be inlinable in downstream crates. @@ -1094,43 +1093,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -fn should_encode_constness(def_kind: DefKind) -> bool { - match def_kind { - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::AssocTy - | DefKind::Fn - | DefKind::Const - | DefKind::Static(..) - | DefKind::Ctor(..) - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy - | DefKind::ImplTraitPlaceholder - | DefKind::Impl - | DefKind::Closure - | DefKind::Generator - | DefKind::TyAlias => true, - DefKind::Variant - | DefKind::TraitAlias - | DefKind::ForeignTy - | DefKind::Field - | DefKind::TyParam - | DefKind::Mod - | DefKind::ForeignMod - | DefKind::ConstParam - | DefKind::Macro(..) - | DefKind::Use - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } -} - fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { if tcx.def_kind(def_id) != DefKind::AssocFn { return false; @@ -1239,9 +1201,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } - if should_encode_constness(def_kind) { - self.tables.constness.set(def_id.index, tcx.constness(def_id)); - } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { @@ -1269,6 +1228,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index @@ -1296,6 +1256,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1329,14 +1290,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // from name resolution point of view. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - yield foreign_item.id.def_id.def_id.local_def_index; + yield foreign_item.id.owner_id.def_id.local_def_index; } } // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, - _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { - yield item_id.def_id.def_id.local_def_index; + hir::ItemKind::Struct(ref vdata, _) => { + yield item_id.owner_id.def_id.local_def_index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_hir_id) = vdata.ctor_hir_id() { + yield tcx.hir().local_def_id(ctor_hir_id).local_def_index; + } + } + _ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => { + yield item_id.owner_id.def_id.local_def_index; } _ => continue, } @@ -1359,6 +1327,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.repr_options[def_id] <- adt_def.repr()); record!(self.tables.variant_data[def_id] <- data); + self.tables.constness.set(def_id.index, hir::Constness::Const); if variant.ctor_kind == CtorKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } @@ -1394,6 +1363,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } }; self.tables.asyncness.set(def_id.index, m_sig.header.asyncness); + self.tables.constness.set(def_id.index, hir::Constness::NotConst); } ty::AssocKind::Type => { self.encode_explicit_item_bounds(def_id); @@ -1418,6 +1388,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() }; self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + // Can be inside `impl const Trait`, so using sig.header.constness is not reliable + let constness = if self.tcx.is_const_fn_raw(def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; + self.tables.constness.set(def_id.index, constness); } ty::AssocKind::Const | ty::AssocKind::Type => {} } @@ -1555,6 +1532,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Fn(ref sig, .., body) => { self.tables.asyncness.set(def_id.index, sig.header.asyncness); record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body)); + self.tables.constness.set(def_id.index, sig.header.constness); } hir::ItemKind::Macro(ref macro_def, _) => { if macro_def.macro_rules { @@ -1563,7 +1541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.def_id.def_id, m); + return self.encode_info_for_mod(item.owner_id.def_id, m); } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); @@ -1575,6 +1553,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); record!(self.tables.repr_options[def_id] <- adt_def.repr()); + self.tables.constness.set(def_id.index, hir::Constness::Const); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method @@ -1603,8 +1582,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_non_exhaustive: variant.is_field_list_non_exhaustive(), }); } - hir::ItemKind::Impl(hir::Impl { defaultness, .. }) => { + hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => { self.tables.impl_defaultness.set(def_id.index, *defaultness); + self.tables.constness.set(def_id.index, *constness); let trait_ref = self.tcx.impl_trait_ref(def_id); if let Some(trait_ref) = trait_ref { @@ -1646,12 +1626,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <- - self.tcx.adt_def(def_id).variants().iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - }) - ), + hir::ItemKind::Enum(..) => { + record_array!(self.tables.children[def_id] <- iter::from_generator(|| + for variant in tcx.adt_def(def_id).variants() { + yield variant.def_id.index; + // Encode constructors which take a separate slot in value namespace. + if let Some(ctor_def_id) = variant.ctor_def_id { + yield ctor_def_id.index; + } + } + )) + } hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { record_array!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { @@ -1688,7 +1673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // normally in the visitor walk. match item.kind { hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_id.to_def_id()); for (i, variant) in def.variants().iter_enumerated() { self.encode_enum_variant_info(def, i); @@ -1698,7 +1683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } hir::ItemKind::Struct(ref struct_def, _) => { - let def = self.tcx.adt_def(item.def_id.to_def_id()); + let def = self.tcx.adt_def(item.owner_id.to_def_id()); // If the struct has a constructor, encode it. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); @@ -1707,13 +1692,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::Impl { .. } => { for &trait_item_def_id in - self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter() { self.encode_info_for_impl_item(trait_item_def_id); } } hir::ItemKind::Trait(..) => { - for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter() + for &item_def_id in + self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter() { self.encode_info_for_trait_item(item_def_id); } @@ -1954,8 +1940,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { FxHashMap::default(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { + if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), @@ -1965,7 +1951,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fx_hash_map .entry(trait_ref.def_id) .or_default() - .push((id.def_id.def_id.local_def_index, simplified_self_ty)); + .push((id.owner_id.def_id.local_def_index, simplified_self_ty)); } } } @@ -2106,12 +2092,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { intravisit::walk_item(self, item); match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.encode_info_for_item(item.def_id.to_def_id(), item), + _ => self.encode_info_for_item(item.owner_id.to_def_id(), item), } } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) { intravisit::walk_foreign_item(self, ni); - self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni); + self.encode_info_for_foreign_item(ni.owner_id.to_def_id(), ni); } fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { intravisit::walk_generics(self, generics); @@ -2330,8 +2316,8 @@ pub fn provide(providers: &mut Providers) { let mut traits = Vec::new(); for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Trait | DefKind::TraitAlias) { - traits.push(id.def_id.to_def_id()) + if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) { + traits.push(id.owner_id.to_def_id()) } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index d2847e4bc12..f8aae86fe3d 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -77,7 +77,7 @@ macro_rules! arena_types { rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, [] all_traits: Vec<rustc_hir::def_id::DefId>, - [] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, + [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, [] foreign_module: rustc_session::cstore::ForeignModule, [] foreign_modules: Vec<rustc_session::cstore::ForeignModule>, [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, @@ -96,7 +96,7 @@ macro_rules! arena_types { // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `librustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, - [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, + [decode] used_trait_imports: rustc_data_structures::unord::UnordSet<rustc_hir::def_id::LocalDefId>, [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>, [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 302f12a6f7d..83a4d16d7a9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -354,19 +354,19 @@ impl<'hir> Map<'hir> { } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item() + self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { @@ -1377,14 +1377,14 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_item(&mut self, item: &'hir Item<'hir>) { if associated_body(Node::Item(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.items.push(item.item_id()); // Items that are modules are handled here instead of in visit_mod. if let ItemKind::Mod(module) = &item.kind { - self.submodules.push(item.def_id); + self.submodules.push(item.owner_id); // A module collector does not recurse inside nested modules. if self.crate_collector { intravisit::walk_mod(self, module, item.hir_id()); @@ -1413,7 +1413,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { if associated_body(Node::TraitItem(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.trait_items.push(item.trait_item_id()); @@ -1422,7 +1422,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { if associated_body(Node::ImplItem(item)).is_some() { - self.body_owners.push(item.def_id.def_id); + self.body_owners.push(item.owner_id.def_id); } self.impl_items.push(item.impl_item_id()); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 1ce98a03c8a..1c6264ad036 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -67,10 +67,10 @@ impl ModuleItems { pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ { self.items .iter() - .map(|id| id.def_id.def_id) - .chain(self.trait_items.iter().map(|id| id.def_id.def_id)) - .chain(self.impl_items.iter().map(|id| id.def_id.def_id)) - .chain(self.foreign_items.iter().map(|id| id.def_id.def_id)) + .map(|id| id.owner_id.def_id) + .chain(self.trait_items.iter().map(|id| id.owner_id.def_id)) + .chain(self.impl_items.iter().map(|id| id.owner_id.def_id)) + .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id)) } pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index f4f1d82c3b8..d3cf519b633 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -302,8 +302,10 @@ impl<'tcx, V> Canonical<'tcx, V> { } } -pub type QueryOutlivesConstraint<'tcx> = - (ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>, ConstraintCategory); +pub type QueryOutlivesConstraint<'tcx> = ( + ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>, + ConstraintCategory<'tcx>, +); TrivialTypeTraversalAndLiftImpls! { for <'tcx> { diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 556bd24d00f..9c68c750475 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -9,120 +9,101 @@ use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::{DefId, LocalDefId}; use std::hash::Hash; -/// Represents the levels of accessibility an item can have. +/// Represents the levels of effective visibility an item can have. /// -/// The variants are sorted in ascending order of accessibility. +/// The variants are sorted in ascending order of directness. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, HashStable)] -pub enum AccessLevel { - /// Superset of `AccessLevel::Reachable` used to mark impl Trait items. - ReachableFromImplTrait, - /// Exported items + items participating in various kinds of public interfaces, - /// but not directly nameable. For example, if function `fn f() -> T {...}` is - /// public, then type `T` is reachable. Its values can be obtained by other crates - /// even if the type itself is not nameable. +pub enum Level { + /// Superset of `Reachable` including items leaked through return position `impl Trait`. + ReachableThroughImplTrait, + /// Item is either reexported, or leaked through any kind of interface. + /// For example, if function `fn f() -> T {...}` is directly public, then type `T` is publicly + /// reachable and its values can be obtained by other crates even if the type itself is not + /// nameable. Reachable, - /// Public items + items accessible to other crates with the help of `pub use` re-exports. - Exported, - /// Items accessible to other crates directly, without the help of re-exports. - Public, + /// Item is accessible either directly, or with help of `use` reexports. + Reexported, + /// Item is directly accessible, without help of reexports. + Direct, } -impl AccessLevel { - pub fn all_levels() -> [AccessLevel; 4] { - [ - AccessLevel::Public, - AccessLevel::Exported, - AccessLevel::Reachable, - AccessLevel::ReachableFromImplTrait, - ] +impl Level { + pub fn all_levels() -> [Level; 4] { + [Level::Direct, Level::Reexported, Level::Reachable, Level::ReachableThroughImplTrait] } } #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] pub struct EffectiveVisibility { - public: Visibility, - exported: Visibility, + direct: Visibility, + reexported: Visibility, reachable: Visibility, - reachable_from_impl_trait: Visibility, + reachable_through_impl_trait: Visibility, } impl EffectiveVisibility { - pub fn get(&self, tag: AccessLevel) -> &Visibility { - match tag { - AccessLevel::Public => &self.public, - AccessLevel::Exported => &self.exported, - AccessLevel::Reachable => &self.reachable, - AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait, + pub fn at_level(&self, level: Level) -> &Visibility { + match level { + Level::Direct => &self.direct, + Level::Reexported => &self.reexported, + Level::Reachable => &self.reachable, + Level::ReachableThroughImplTrait => &self.reachable_through_impl_trait, } } - fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility { - match tag { - AccessLevel::Public => &mut self.public, - AccessLevel::Exported => &mut self.exported, - AccessLevel::Reachable => &mut self.reachable, - AccessLevel::ReachableFromImplTrait => &mut self.reachable_from_impl_trait, + fn at_level_mut(&mut self, level: Level) -> &mut Visibility { + match level { + Level::Direct => &mut self.direct, + Level::Reexported => &mut self.reexported, + Level::Reachable => &mut self.reachable, + Level::ReachableThroughImplTrait => &mut self.reachable_through_impl_trait, } } - pub fn is_public_at_level(&self, tag: AccessLevel) -> bool { - self.get(tag).is_public() + pub fn is_public_at_level(&self, level: Level) -> bool { + self.at_level(level).is_public() } - fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool { - let mut changed = false; - for level in AccessLevel::all_levels() { - if level <= tag { - let current_effective_vis = self.get_mut(level); - if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) { - changed = true; - *current_effective_vis = vis; - } - } - } - changed - } - - fn from_vis(vis: Visibility) -> EffectiveVisibility { + pub fn from_vis(vis: Visibility) -> EffectiveVisibility { EffectiveVisibility { - public: vis, - exported: vis, + direct: vis, + reexported: vis, reachable: vis, - reachable_from_impl_trait: vis, + reachable_through_impl_trait: vis, } } } -/// Holds a map of accessibility levels for reachable HIR nodes. +/// Holds a map of effective visibilities for reachable HIR nodes. #[derive(Debug, Clone)] -pub struct AccessLevels<Id = LocalDefId> { +pub struct EffectiveVisibilities<Id = LocalDefId> { map: FxHashMap<Id, EffectiveVisibility>, } -impl<Id: Hash + Eq + Copy> AccessLevels<Id> { - pub fn is_public_at_level(&self, id: Id, tag: AccessLevel) -> bool { - self.get_effective_vis(id) - .map_or(false, |effective_vis| effective_vis.is_public_at_level(tag)) +impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> { + pub fn is_public_at_level(&self, id: Id, level: Level) -> bool { + self.effective_vis(id) + .map_or(false, |effective_vis| effective_vis.is_public_at_level(level)) } - /// See `AccessLevel::Reachable`. + /// See `Level::Reachable`. pub fn is_reachable(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Reachable) + self.is_public_at_level(id, Level::Reachable) } - /// See `AccessLevel::Exported`. + /// See `Level::Reexported`. pub fn is_exported(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Exported) + self.is_public_at_level(id, Level::Reexported) } - /// See `AccessLevel::Public`. - pub fn is_public(&self, id: Id) -> bool { - self.is_public_at_level(id, AccessLevel::Public) + /// See `Level::Direct`. + pub fn is_directly_public(&self, id: Id) -> bool { + self.is_public_at_level(id, Level::Direct) } - pub fn get_access_level(&self, id: Id) -> Option<AccessLevel> { - self.get_effective_vis(id).and_then(|effective_vis| { - for level in AccessLevel::all_levels() { + pub fn public_at_level(&self, id: Id) -> Option<Level> { + self.effective_vis(id).and_then(|effective_vis| { + for level in Level::all_levels() { if effective_vis.is_public_at_level(level) { return Some(level); } @@ -131,7 +112,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> { }) } - pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { + pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> { self.map.get(&id) } @@ -139,30 +120,33 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> { self.map.iter() } - pub fn map_id<OutId: Hash + Eq + Copy>(&self, f: impl Fn(Id) -> OutId) -> AccessLevels<OutId> { - AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } + pub fn map_id<OutId: Hash + Eq + Copy>( + &self, + f: impl Fn(Id) -> OutId, + ) -> EffectiveVisibilities<OutId> { + EffectiveVisibilities { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() } } - pub fn set_access_level( + pub fn set_public_at_level( &mut self, id: Id, default_vis: impl FnOnce() -> Visibility, - tag: AccessLevel, + level: Level, ) { let mut effective_vis = self - .get_effective_vis(id) + .effective_vis(id) .copied() .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); - for level in AccessLevel::all_levels() { - if level <= tag { - *effective_vis.get_mut(level) = Visibility::Public; + for l in Level::all_levels() { + if l <= level { + *effective_vis.at_level_mut(l) = Visibility::Public; } } self.map.insert(id, effective_vis); } } -impl<Id: Hash + Eq + Copy + Into<DefId>> AccessLevels<Id> { +impl<Id: Hash + Eq + Copy + Into<DefId>> EffectiveVisibilities<Id> { // `parent_id` is not necessarily a parent in source code tree, // it is the node from which the maximum effective visibility is inherited. pub fn update( @@ -171,47 +155,64 @@ impl<Id: Hash + Eq + Copy + Into<DefId>> AccessLevels<Id> { nominal_vis: Visibility, default_vis: impl FnOnce() -> Visibility, parent_id: Id, - tag: AccessLevel, + level: Level, tree: impl DefIdTree, - ) -> Result<bool, ()> { + ) -> bool { let mut changed = false; - let mut current_effective_vis = self - .get_effective_vis(id) - .copied() - .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis())); - if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) { - for level in AccessLevel::all_levels() { - if tag >= level { - let inherited_effective_vis_at_level = *inherited_effective_vis.get(level); - let calculated_effective_vis = - if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { - inherited_effective_vis_at_level - } else { - nominal_vis - }; - changed |= current_effective_vis.update(calculated_effective_vis, level, tree); - } + let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| { + if id.into().is_crate_root() { + EffectiveVisibility::from_vis(Visibility::Public) + } else { + EffectiveVisibility::from_vis(default_vis()) } - } else { - if !id.into().is_crate_root() { - return Err(()); + }); + if let Some(inherited_effective_vis) = self.effective_vis(parent_id) { + let mut inherited_effective_vis_at_prev_level = + *inherited_effective_vis.at_level(level); + let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; + for l in Level::all_levels() { + if level >= l { + let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l); + let current_effective_vis_at_level = current_effective_vis.at_level_mut(l); + // effective visibility for id shouldn't be recalculated if + // inherited from parent_id effective visibility isn't changed at next level + if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level + && level != l) + { + calculated_effective_vis = + if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) { + inherited_effective_vis_at_level + } else { + nominal_vis + }; + } + // effective visibility can't be decreased at next update call for the + // same id + if *current_effective_vis_at_level != calculated_effective_vis + && calculated_effective_vis + .is_at_least(*current_effective_vis_at_level, tree) + { + changed = true; + *current_effective_vis_at_level = calculated_effective_vis; + } + inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level; + } } - changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree); } self.map.insert(id, current_effective_vis); - Ok(changed) + changed } } -impl<Id> Default for AccessLevels<Id> { +impl<Id> Default for EffectiveVisibilities<Id> { fn default() -> Self { - AccessLevels { map: Default::default() } + EffectiveVisibilities { map: Default::default() } } } -impl<'a> HashStable<StableHashingContext<'a>> for AccessLevels { +impl<'a> HashStable<StableHashingContext<'a>> for EffectiveVisibilities { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let AccessLevels { ref map } = *self; + let EffectiveVisibilities { ref map } = *self; map.hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e0e823e2090..79db35a764a 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -116,11 +116,6 @@ pub trait MirPass<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); - /// If this pass causes the MIR to enter a new phase, return that phase. - fn phase_change(&self) -> Option<MirPhase> { - None - } - fn is_mir_dump_enabled(&self) -> bool { true } @@ -145,6 +140,35 @@ impl MirPhase { } } +impl Display for MirPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + MirPhase::Built => write!(f, "built"), + MirPhase::Analysis(p) => write!(f, "analysis-{}", p), + MirPhase::Runtime(p) => write!(f, "runtime-{}", p), + } + } +} + +impl Display for AnalysisPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AnalysisPhase::Initial => write!(f, "initial"), + AnalysisPhase::PostCleanup => write!(f, "post_cleanup"), + } + } +} + +impl Display for RuntimePhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + RuntimePhase::Initial => write!(f, "initial"), + RuntimePhase::PostCleanup => write!(f, "post_cleanup"), + RuntimePhase::Optimized => write!(f, "optimized"), + } + } +} + /// Where a specific `mir::Body` comes from. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] @@ -207,6 +231,9 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, + /// How many passses we have executed since starting the current phase. Used for debug output. + pub pass_count: usize, + pub source: MirSource<'tcx>, /// A list of source scopes; these are referenced by statements @@ -292,6 +319,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source, basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, @@ -325,6 +353,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), @@ -2875,7 +2904,7 @@ fn pretty_print_const_value<'tcx>( /// `Location` represents the position of the start of the statement; or, if /// `statement_index` equals the number of statements, then the start of the /// terminator. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] pub struct Location { /// The block that the location is within. pub block: BasicBlock, diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index fdda62719ee..15a24aa4ace 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -81,7 +81,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::Fn(instance) => tcx.symbol_name(instance), MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)), MonoItem::GlobalAsm(item_id) => { - SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id)) + SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.owner_id)) } } } @@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), MonoItem::Static(def_id) => def_id.as_local(), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id), } .map(|def_id| tcx.def_span(def_id)) } @@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> { } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id.index()), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.index()), }, item.symbol_name(tcx), ) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 1d847d8f3d3..efd7357afc4 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -15,7 +15,7 @@ use smallvec::SmallVec; use std::cell::Cell; use std::fmt::{self, Debug}; -use super::{Field, Location, SourceInfo}; +use super::{Field, SourceInfo}; #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationKind { @@ -314,12 +314,12 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub blame_span: Span, // ... due to this reason. - pub category: ConstraintCategory, + pub category: ConstraintCategory<'tcx>, } // Make sure this enum doesn't unintentionally grow #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(ConstraintCategory, 16); +rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort @@ -327,8 +327,8 @@ rustc_data_structures::static_assert_size!(ConstraintCategory, 16); /// /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable)] -pub enum ConstraintCategory { +#[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] +pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, UseAsConst, @@ -342,7 +342,7 @@ pub enum ConstraintCategory { ClosureBounds, /// Contains the function type if available. - CallArgument(Location), + CallArgument(Option<Ty<'tcx>>), CopyBound, SizedBound, Assignment, @@ -368,10 +368,6 @@ pub enum ConstraintCategory { Internal, } -TrivialTypeTraversalAndLiftImpls! { - ConstraintCategory, -} - #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ReturnConstraint { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2ab3b0d27c8..3d720f09b4f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -23,7 +23,7 @@ rustc_queries! { desc { "triggering a delay span bug" } } - query resolutions(_: ()) -> &'tcx ty::ResolverOutputs { + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { eval_always no_hash desc { "getting the resolver outputs" } @@ -912,7 +912,7 @@ rustc_queries! { cache_on_disk_if { true } } - query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet<LocalDefId> { + query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> { desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } } @@ -1065,10 +1065,10 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - /// Performs part of the privacy check and computes "access levels". - query privacy_access_levels(_: ()) -> &'tcx AccessLevels { + /// Performs part of the privacy check and computes effective visibilities. + query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { eval_always - desc { "checking privacy access levels" } + desc { "checking effective visibilities" } } query check_private_in_public(_: ()) -> () { eval_always diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3adc2e1b73e..e73d44bbb36 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -185,7 +185,7 @@ impl<'tcx> ObligationCause<'tcx> { self } - pub fn to_constraint_category(&self) -> ConstraintCategory { + pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self.code() { MatchImpl(cause, _) => cause.to_constraint_category(), AscribeUserTypeProvePredicate(predicate_span) => { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0816a5cb8f1..3d7e2a0839a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -34,6 +34,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal}; +use rustc_data_structures::unord::UnordSet; use rustc_data_structures::vec_map::VecMap; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -79,7 +80,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::{ImplPolarity, RvalueScopes}; +use super::{ImplPolarity, ResolverOutputs, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -531,7 +532,7 @@ pub struct TypeckResults<'tcx> { /// This is used for warning unused imports. During type /// checking, this `Lrc` should not be cloned: it must have a ref-count /// of 1 so that we can insert things into the set mutably. - pub used_trait_imports: Lrc<FxHashSet<LocalDefId>>, + pub used_trait_imports: Lrc<UnordSet<LocalDefId>>, /// If any errors occurred while type-checking this body, /// this field will be set to `Some(ErrorGuaranteed)`. @@ -1067,10 +1068,9 @@ pub struct GlobalCtxt<'tcx> { pub consts: CommonConsts<'tcx>, definitions: RwLock<Definitions>, - cstore: Box<CrateStoreDyn>, /// Output of the resolver. - pub(crate) untracked_resolutions: ty::ResolverOutputs, + pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>, /// The entire crate as AST. This field serves as the input for the hir_crate query, /// which lowers it from AST to HIR. It must not be read or used by anything else. @@ -1233,10 +1233,7 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc<dyn Any + sync::Send + sync::Sync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, - definitions: Definitions, - cstore: Box<CrateStoreDyn>, - untracked_resolutions: ty::ResolverOutputs, - untracked_resolver_for_lowering: ty::ResolverAstLowering, + resolver_outputs: ResolverOutputs, krate: Lrc<ast::Crate>, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, @@ -1245,6 +1242,11 @@ impl<'tcx> TyCtxt<'tcx> { crate_name: &str, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { + let ResolverOutputs { + definitions, + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver_outputs; let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { s.emit_fatal(err); }); @@ -1253,7 +1255,7 @@ impl<'tcx> TyCtxt<'tcx> { &interners, s, &definitions, - &*cstore, + &*untracked_resolutions.cstore, // This is only used to create a stable hashing context. &untracked_resolutions.source_span, ); @@ -1268,7 +1270,6 @@ impl<'tcx> TyCtxt<'tcx> { interners, dep_graph, definitions: RwLock::new(definitions), - cstore, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, @@ -1369,7 +1370,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_key(id) } else { - self.cstore.def_key(id) + self.untracked_resolutions.cstore.def_key(id) } } @@ -1383,7 +1384,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_path(id) } else { - self.cstore.def_path(id) + self.untracked_resolutions.cstore.def_path(id) } } @@ -1393,7 +1394,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(def_id) = def_id.as_local() { self.definitions_untracked().def_path_hash(def_id) } else { - self.cstore.def_path_hash(def_id) + self.untracked_resolutions.cstore.def_path_hash(def_id) } } @@ -1402,7 +1403,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.cstore.stable_crate_id(crate_num) + self.untracked_resolutions.cstore.stable_crate_id(crate_num) } } @@ -1413,7 +1414,7 @@ impl<'tcx> TyCtxt<'tcx> { if stable_crate_id == self.sess.local_stable_crate_id() { LOCAL_CRATE } else { - self.cstore.stable_crate_id_to_crate_num(stable_crate_id) + self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) } } @@ -1432,8 +1433,9 @@ impl<'tcx> TyCtxt<'tcx> { } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. - let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id); - self.cstore.def_path_hash_to_def_id(cnum, hash) + let cstore = &*self.untracked_resolutions.cstore; + let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); + cstore.def_path_hash_to_def_id(cnum, hash) } } @@ -1445,7 +1447,7 @@ impl<'tcx> TyCtxt<'tcx> { let (crate_name, stable_crate_id) = if def_id.is_local() { (self.crate_name, self.sess.local_stable_crate_id()) } else { - let cstore = &self.cstore; + let cstore = &*self.untracked_resolutions.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; @@ -1520,7 +1522,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { - &*self.cstore + &*self.untracked_resolutions.cstore } /// Note that this is *untracked* and should only be used within the query @@ -1546,7 +1548,7 @@ impl<'tcx> TyCtxt<'tcx> { let hcx = StableHashingContext::new( self.sess, &*definitions, - &*self.cstore, + &*self.untracked_resolutions.cstore, &self.untracked_resolutions.source_span, ); f(hcx) @@ -2364,7 +2366,7 @@ impl<'tcx> TyCtxt<'tcx> { st, self.sess, &self.definitions.read(), - &*self.cstore, + &*self.untracked_resolutions.cstore, // This is only used to create a stable hashing context. &self.untracked_resolutions.source_span, ) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 52f16ad88f6..4e6cdb78602 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -872,9 +872,9 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: account for returning some type in a trait fn impl that has // an assoc type as a return type (#72076). if let hir::Defaultness::Default { has_value: true } = - self.impl_defaultness(item.id.def_id) + self.impl_defaultness(item.id.owner_id) { - if self.type_of(item.id.def_id) == found { + if self.type_of(item.id.owner_id) == found { diag.span_label( item.span, "associated type defaults can't be assumed inside the \ @@ -894,7 +894,7 @@ fn foo(&self) -> Self::T { String::new() } })) => { for item in &items[..] { if let hir::AssocItemKind::Type = item.kind { - if self.type_of(item.id.def_id) == found { + if self.type_of(item.id.owner_id) == found { diag.span_label(item.span, "expected this associated type"); return true; } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0a109fd8f44..3312f44c67b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -830,7 +830,7 @@ where } else { match mt { hir::Mutability::Not => { - if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { + if ty.is_freeze(tcx, cx.param_env()) { PointerKind::Frozen } else { PointerKind::SharedMutable @@ -841,7 +841,7 @@ where // noalias, as another pointer to the structure can be obtained, that // is not based-on the original reference. We consider all !Unpin // types to be potentially self-referential here. - if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { + if ty.is_unpin(tcx, cx.param_env()) { PointerKind::UniqueBorrowed } else { PointerKind::UniqueBorrowedPinned diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c2aef8178e2..a42d0570613 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -17,7 +17,7 @@ pub use self::IntVarValue::*; pub use self::Variance::*; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; -use crate::middle::privacy::AccessLevels; +use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; @@ -38,11 +38,13 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; +use rustc_hir::definitions::Definitions; use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; +use rustc_session::cstore::CrateStoreDyn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; @@ -142,8 +144,15 @@ mod sty; pub type RegisteredTools = FxHashSet<Ident>; -#[derive(Debug)] pub struct ResolverOutputs { + pub definitions: Definitions, + pub global_ctxt: ResolverGlobalCtxt, + pub ast_lowering: ResolverAstLowering, +} + +#[derive(Debug)] +pub struct ResolverGlobalCtxt { + 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, @@ -151,7 +160,7 @@ pub struct ResolverOutputs { pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, /// Reference span for definitions. pub source_span: IndexVec<LocalDefId, Span>, - pub access_levels: AccessLevels, + pub effective_visibilities: EffectiveVisibilities, pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, @@ -2595,7 +2604,9 @@ impl<'tcx> TyCtxt<'tcx> { && if self.features().collapse_debuginfo { span.in_macro_expansion_with_collapse_debuginfo() } else { - span.from_expansion() + // Inlined spans should not be collapsed as that leads to all of the + // inlined code being attributed to the inline callsite. + span.from_expansion() && !span.is_inlined() } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b8ee2b994b1..ef9aa236bac 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,6 +63,7 @@ thread_local! { static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) }; static NO_QUERIES: Cell<bool> = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) }; + static NO_VERBOSE_CONSTANTS: Cell<bool> = const { Cell::new(false) }; } macro_rules! define_helper { @@ -117,6 +118,9 @@ define_helper!( /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); + /// Prevent verbose printing of constants. Verbose printing of constants is + /// never desirable in some contexts like `std::any::type_name`. + fn with_no_verbose_constants(NoVerboseConstantsGuard, NO_VERBOSE_CONSTANTS); ); /// The "region highlights" are used to control region printing during @@ -759,7 +763,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Array(ty, sz) => { p!("[", print(ty), "; "); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.kind() { // Do not try to evaluate unevaluated constants. If we are const evaluating an @@ -1181,7 +1185,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("Const({:?}: {:?})", ct.kind(), ct.ty())); return Ok(self); } @@ -1416,7 +1420,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); - if self.tcx().sess.verbose() { + if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { p!(write("ValTree({:?}: ", valtree), print(ty), ")"); return Ok(self); } @@ -2736,7 +2740,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N // Iterate all local crate items no matter where they are defined. let hir = tcx.hir(); for id in hir.items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Use) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Use) { continue; } @@ -2745,7 +2749,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N continue; } - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS); collect_fn(&item.ident, ns, def_id); } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 9c97ce34f29..ec90590ada2 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -5,7 +5,7 @@ use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; -use crate::middle::privacy::AccessLevels; +use crate::middle::privacy::EffectiveVisibilities; use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes}; use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; @@ -40,6 +40,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::unord::UnordSet; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index cdb618e030a..b25b4bd4fe3 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( /// it. pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, + mut a: ty::Const<'tcx>, + mut b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); @@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( ); } + // HACK(const_generics): We still need to eagerly evaluate consts when + // relating them because during `normalize_param_env_or_error`, + // we may relate an evaluated constant in a obligation against + // an unnormalized (i.e. unevaluated) const in the param-env. + // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants + // these `eval` calls can be removed. + if !relation.tcx().features().generic_const_exprs { + a = a.eval(tcx, relation.param_env()); + b = b.eval(tcx, relation.param_env()); + } + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f73d062ba30..f72e236eda1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,7 +2,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::layout::IntegerExt; -use crate::ty::query::TyCtxtAt; use crate::ty::{ self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, @@ -821,12 +820,8 @@ impl<'tcx> Ty<'tcx> { /// does copies even when the type actually doesn't satisfy the /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions( - self, - tcx_at: TyCtxtAt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> bool { - self.is_trivially_pure_clone_copy() || tcx_at.is_copy_raw(param_env.and(self)) + pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self)) } /// Checks whether values of this type `T` have a size known at @@ -835,8 +830,8 @@ impl<'tcx> Ty<'tcx> { /// over-approximation in generic contexts, where one can have /// strange rules like `<T as Foo<'static>>::Bar: Sized` that /// actually carry lifetime requirements. - pub fn is_sized(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self)) + pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self)) } /// Checks whether values of this type `T` implement the `Freeze` @@ -846,8 +841,8 @@ impl<'tcx> Ty<'tcx> { /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - pub fn is_freeze(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) + pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self)) } /// Fast path helper for testing if a type is `Freeze`. @@ -886,8 +881,8 @@ impl<'tcx> Ty<'tcx> { } /// Checks whether values of this type `T` implement the `Unpin` trait. - pub fn is_unpin(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) + pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self)) } /// Fast path helper for testing if a type is `Unpin`. diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index e707c373f0d..c8610af7038 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -153,12 +153,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if tcx.features().unsized_fn_params { let ty = expr.ty; - let span = expr.span; let param_env = this.param_env; - if !ty.is_sized(tcx.at(span), param_env) { + if !ty.is_sized(tcx, param_env) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env)); + assert!(!ty.is_copy_modulo_regions(tcx, param_env)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 5e8ce65daf0..fb1ea9ed300 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; match borrow_kind { BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { - if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { + if !ty.is_freeze(self.tcx, self.param_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } @@ -457,9 +457,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if visitor.found { match borrow_kind { BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique - if !self.thir[arg] - .ty - .is_freeze(self.tcx.at(self.thir[arg].span), self.param_env) => + if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 5984c800d83..a9e5e438cf5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -507,7 +507,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { _ => "aren't", }, ), - " else { todo!() }".to_string(), + " else { todo!() }", Applicability::HasPlaceholders, ); } @@ -1004,8 +1004,8 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId, span: Span) -> bool { - !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env) +fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool { + !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env) } /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. @@ -1031,7 +1031,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Get the binding move, extract the mutability if by-ref. let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) { - Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id, pat.span) => { + Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); sub.each_binding(|_, hir_id, span, _| { @@ -1070,7 +1070,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`. _ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction. }, - Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => { + Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => { conflicts_move.push((span, name)) // `ref mut?` + by-move conflict. } Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine. diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cf8ae776be9..ad12e011621 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -506,7 +506,7 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx.at(span), param_env) { + if !pointee_ty.is_sized(tcx, param_env) { // `tcx.deref_mir_constant()` below will ICE with an unsized type // (except slices, which are handled in a separate arm above). let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty); @@ -534,7 +534,7 @@ impl<'tcx> ConstToPat<'tcx> { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { PatKind::Constant { value: cv } } - ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => { + ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => { PatKind::Constant { value: cv } } // FIXME: these can have very surprising behaviour where optimization levels or other diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 895af80bd7f..2526522a25c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -483,7 +483,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Use `Reveal::All` here because patterns are always monomorphic even if their function // isn't. let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); - let substs = self.typeck_results.node_substs(id); + // N.B. There is no guarantee that substs collected in typeck results are fully normalized, + // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE + // if given unnormalized types. + let substs = self + .tcx + .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id)); let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { Ok(Some(i)) => i, Ok(None) => { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 4730be1244b..f8f04214a2c 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -312,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { } else if !place .ty(self.body, self.tcx) .ty - .is_freeze(self.tcx.at(self.source_info.span), self.param_env) + .is_freeze(self.tcx, self.param_env) { UnsafetyViolationDetails::BorrowOfLayoutConstrainedField } else { diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 4a9bd9df327..4e451588845 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -633,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } if !rvalue .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(self.ecx.tcx, self.param_env) + .is_sized(*self.ecx.tcx, self.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 6bddbdb8e6a..479c4e577d4 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -500,7 +500,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } if !rvalue .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) - .is_sized(self.ecx.tcx, self.param_env) + .is_sized(*self.ecx.tcx, self.param_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 18352fbf675..28b1c5a4809 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -11,7 +11,6 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE}; use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; -use rustc_span::DUMMY_SP; /// A visitor that determines which arguments have been mutated. We can't use the mutability field /// on LocalDecl for this because it has no meaning post-optimization. @@ -232,7 +231,7 @@ pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [Ded body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { read_only: !deduce_read_only.mutable_args.contains(arg_index) - && local_decl.ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()), + && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()), }, ), ); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5c411fa5657..5be2232547b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -71,7 +71,6 @@ mod inline; mod instcombine; mod lower_intrinsics; mod lower_slice_len; -mod marker; mod match_branches; mod multiple_return_terminators; mod normalize_array_len; @@ -303,6 +302,7 @@ fn mir_const<'tcx>( &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, // Just a lint ], + None, ); tcx.alloc_steal_mir(body) } @@ -342,6 +342,7 @@ fn mir_promoted<'tcx>( &simplify::SimplifyCfg::new("promote-consts"), &coverage::InstrumentCoverage, ], + Some(MirPhase::Analysis(AnalysisPhase::Initial)), ); let promoted = promote_pass.promoted_fragments.into_inner(); @@ -409,10 +410,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) - pm::run_passes( tcx, &mut body, - &[ - &const_prop::ConstProp, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), - ], + &[&const_prop::ConstProp], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); } } @@ -474,6 +473,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx> &remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::new("remove-false-edges"), ], + None, ); check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint } @@ -498,10 +498,9 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), &deref_separator::Derefer, - &marker::PhaseChange(MirPhase::Analysis(AnalysisPhase::PostCleanup)), ]; - pm::run_passes(tcx, body, passes); + pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup))); } /// Returns the sequence of passes that lowers analysis to runtime MIR. @@ -526,9 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // CTFE support for aggregates. &deaggregator::Deaggregator, &Lint(const_prop_lint::ConstProp), - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Initial)), ]; - pm::run_passes_no_validate(tcx, body, passes); + pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial))); } /// Returns the sequence of passes that do the initial cleanup of runtime MIR. @@ -537,10 +535,9 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &elaborate_box_derefs::ElaborateBoxDerefs, &lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops"), - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::PostCleanup)), ]; - pm::run_passes(tcx, body, passes); + pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup))); } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -591,10 +588,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &deduplicate_blocks::DeduplicateBlocks, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), // Dump the end result for testing and debugging purposes. &dump_mir::Marker("PreCodegen"), ], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); } diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs deleted file mode 100644 index 06819fc1d37..00000000000 --- a/compiler/rustc_mir_transform/src/marker.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::borrow::Cow; - -use crate::MirPass; -use rustc_middle::mir::{Body, MirPhase}; -use rustc_middle::ty::TyCtxt; - -/// Changes the MIR phase without changing the MIR itself. -pub struct PhaseChange(pub MirPhase); - -impl<'tcx> MirPass<'tcx> for PhaseChange { - fn phase_change(&self) -> Option<MirPhase> { - Some(self.0) - } - - fn name(&self) -> Cow<'_, str> { - Cow::from(format!("PhaseChange-{:?}", self.0)) - } - - fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} -} diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 67dae71468f..230c6a7cb4b 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -66,10 +66,6 @@ where fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.1.run_pass(tcx, body) } - - fn phase_change(&self) -> Option<MirPhase> { - self.1.phase_change() - } } /// Run the sequence of passes without validating the MIR after each pass. The MIR is still @@ -78,23 +74,28 @@ pub fn run_passes_no_validate<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], + phase_change: Option<MirPhase>, ) { - run_passes_inner(tcx, body, passes, false); + run_passes_inner(tcx, body, passes, phase_change, false); } -pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) { - run_passes_inner(tcx, body, passes, true); +/// The optional `phase_change` is applied after executing all the passes, if present +pub fn run_passes<'tcx>( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + passes: &[&dyn MirPass<'tcx>], + phase_change: Option<MirPhase>, +) { + run_passes_inner(tcx, body, passes, phase_change, true); } fn run_passes_inner<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], + phase_change: Option<MirPhase>, validate_each: bool, ) { - let start_phase = body.phase; - let mut cnt = 0; - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); @@ -102,7 +103,6 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - // Gather information about what we should be doing for this pass let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| { trace!( @@ -112,32 +112,44 @@ fn run_passes_inner<'tcx>( ); *polarity }); - let is_enabled = overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)); - let new_phase = pass.phase_change(); - let dump_enabled = (is_enabled && pass.is_mir_dump_enabled()) || new_phase.is_some(); - let validate = (validate && is_enabled) - || new_phase == Some(MirPhase::Runtime(RuntimePhase::Optimized)); + if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) { + continue; + } + + let dump_enabled = pass.is_mir_dump_enabled(); if dump_enabled { - dump_mir(tcx, body, start_phase, &name, cnt, false); - } - if is_enabled { - pass.run_pass(tcx, body); + dump_mir_for_pass(tcx, body, &name, false); } - if dump_enabled { - dump_mir(tcx, body, start_phase, &name, cnt, true); - cnt += 1; + if validate { + validate_body(tcx, body, format!("before pass {}", name)); } - if let Some(new_phase) = pass.phase_change() { - if body.phase >= new_phase { - panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); - } - body.phase = new_phase; + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir_for_pass(tcx, body, &name, true); } if validate { validate_body(tcx, body, format!("after pass {}", name)); } + + body.pass_count += 1; + } + + if let Some(new_phase) = phase_change { + if body.phase >= new_phase { + panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); + } + + body.phase = new_phase; + + dump_mir_for_phase_change(tcx, body); + if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { + validate_body(tcx, body, format!("after phase change to {}", new_phase)); + } + + body.pass_count = 1; } } @@ -145,22 +157,33 @@ pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: Strin validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } -pub fn dump_mir<'tcx>( +pub fn dump_mir_for_pass<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - phase: MirPhase, pass_name: &str, - cnt: usize, is_after: bool, ) { - let phase_index = phase.phase_index(); + let phase_index = body.phase.phase_index(); mir::dump_mir( tcx, - Some(&format_args!("{:03}-{:03}", phase_index, cnt)), + Some(&format_args!("{:03}-{:03}", phase_index, body.pass_count)), pass_name, if is_after { &"after" } else { &"before" }, body, |_, _| Ok(()), ); } + +pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let phase_index = body.phase.phase_index(); + + mir::dump_mir( + tcx, + Some(&format_args!("{:03}-000", phase_index)), + &format!("{}", body.phase), + &"after", + body, + |_, _| Ok(()), + ) +} diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 6ca58ee458c..4e8798b7a55 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -17,7 +17,7 @@ use std::iter; use crate::util::expand_aggregate; use crate::{ - abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, marker, + abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, pass_manager as pm, remove_noop_landing_pads, simplify, }; use rustc_middle::mir::patch::MirPatch; @@ -97,8 +97,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, - &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)), ], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); debug!("make_shim({:?}) = {:?}", instance, result); @@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let param_env = tcx.param_env(def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env); + let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); let dest = Place::return_place(); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5cd7a7f760f..a71218e6997 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1067,7 +1067,7 @@ fn find_vtable_types_for_unsizing<'tcx>( let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let param_env = ty::ParamEnv::reveal_all(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.at(DUMMY_SP), param_env) { + if ty.is_sized(tcx, param_env) { return false; } let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); @@ -1192,7 +1192,7 @@ struct RootCollector<'a, 'tcx> { impl<'v> RootCollector<'_, 'v> { fn process_item(&mut self, id: hir::ItemId) { - match self.tcx.def_kind(id.def_id) { + match self.tcx.def_kind(id.owner_id) { DefKind::Enum | DefKind::Struct | DefKind::Union => { let item = self.tcx.hir().item(id); match item.kind { @@ -1203,12 +1203,14 @@ impl<'v> RootCollector<'_, 'v> { if self.mode == MonoItemCollectionMode::Eager { debug!( "RootCollector: ADT drop-glue for {}", - self.tcx.def_path_str(item.def_id.to_def_id()) + self.tcx.def_path_str(item.owner_id.to_def_id()) ); - let ty = - Instance::new(item.def_id.to_def_id(), InternalSubsts::empty()) - .ty(self.tcx, ty::ParamEnv::reveal_all()); + let ty = Instance::new( + item.owner_id.to_def_id(), + InternalSubsts::empty(), + ) + .ty(self.tcx, ty::ParamEnv::reveal_all()); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } } @@ -1219,23 +1221,23 @@ impl<'v> RootCollector<'_, 'v> { DefKind::GlobalAsm => { debug!( "RootCollector: ItemKind::GlobalAsm({})", - self.tcx.def_path_str(id.def_id.to_def_id()) + self.tcx.def_path_str(id.owner_id.to_def_id()) ); self.output.push(dummy_spanned(MonoItem::GlobalAsm(id))); } DefKind::Static(..) => { debug!( "RootCollector: ItemKind::Static({})", - self.tcx.def_path_str(id.def_id.to_def_id()) + self.tcx.def_path_str(id.owner_id.to_def_id()) ); - self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id()))); + self.output.push(dummy_spanned(MonoItem::Static(id.owner_id.to_def_id()))); } DefKind::Const => { // const items only generate mono items if they are // actually used somewhere. Just declaring them is insufficient. // but even just declaring them must collect the items they refer to - if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) { + if let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) { collect_const_value(self.tcx, val, &mut self.output); } } @@ -1246,15 +1248,15 @@ impl<'v> RootCollector<'_, 'v> { } } DefKind::Fn => { - self.push_if_root(id.def_id.def_id); + self.push_if_root(id.owner_id.def_id); } _ => {} } } fn process_impl_item(&mut self, id: hir::ImplItemId) { - if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) { - self.push_if_root(id.def_id.def_id); + if matches!(self.tcx.def_kind(id.owner_id), DefKind::AssocFn) { + self.push_if_root(id.owner_id.def_id); } } @@ -1352,13 +1354,13 @@ fn create_mono_items_for_default_impls<'tcx>( debug!( "create_mono_items_for_default_impls(item={})", - tcx.def_path_str(item.def_id.to_def_id()) + tcx.def_path_str(item.owner_id.to_def_id()) ); - if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); - let overridden_methods = tcx.impl_item_implementor_ids(item.def_id); + let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains_key(&method.def_id) { continue; diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index 15276569c32..29009c48050 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -319,7 +319,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( Some(def_id) } MonoItem::Static(def_id) => Some(def_id), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.to_def_id()), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()), } } @@ -411,9 +411,9 @@ fn mono_item_visibility<'tcx>( }; } MonoItem::GlobalAsm(item_id) => { - return if tcx.is_reachable_non_generic(item_id.def_id) { + return if tcx.is_reachable_non_generic(item_id.owner_id) { *can_be_internalized = false; - default_visibility(tcx, item_id.def_id.to_def_id(), false) + default_visibility(tcx, item_id.owner_id.to_def_id(), false) } else { Visibility::Hidden }; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ca216b1cd10..a781748efc5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2112,6 +2112,8 @@ impl<'a> Parser<'a> { // HACK: This is needed so we can detect whether we're inside a macro, // where regular assumptions about what tokens can follow other tokens // don't necessarily apply. + && self.may_recover() + // FIXME(Nilstrieb): Remove this check once `may_recover` actually stops recovery && self.subparser_name.is_none() { // It is likely that the closure body is a block but where the diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 89c24920f85..5fe29062b85 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -115,6 +115,12 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { }; } +#[derive(Clone, Copy)] +pub enum Recovery { + Allowed, + Forbidden, +} + #[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, @@ -152,12 +158,15 @@ pub struct Parser<'a> { /// This allows us to recover when the user forget to add braces around /// multiple statements in the closure body. pub current_closure: Option<ClosureSpans>, + /// Whether the parser is allowed to do recovery. + /// This is disabled when parsing macro arguments, see #103534 + pub recovery: Recovery, } -// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure +// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. 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); +rustc_data_structures::static_assert_size!(Parser<'_>, 336); /// Stores span information about a closure. #[derive(Clone)] @@ -483,6 +492,7 @@ impl<'a> Parser<'a> { inner_attr_ranges: Default::default(), }, current_closure: None, + recovery: Recovery::Allowed, }; // Make parser point to the first token. @@ -491,6 +501,22 @@ impl<'a> Parser<'a> { parser } + pub fn forbid_recovery(mut self) -> Self { + self.recovery = Recovery::Forbidden; + self + } + + /// Whether the parser is allowed to recover from broken code. + /// + /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead) + /// is not allowed. All recovery done by the parser must be gated behind this check. + /// + /// Technically, this only needs to restrict eager recovery by doing lookahead at more tokens. + /// But making the distinction is very subtle, and simply forbidding all recovery is a lot simpler to uphold. + fn may_recover(&self) -> bool { + matches!(self.recovery, Recovery::Allowed) + } + pub fn unexpected<T>(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a61e77b7c3b..12753c6785c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -553,39 +553,46 @@ impl<'a> Parser<'a> { match stmt.kind { // Expression without semicolon. StmtKind::Expr(ref mut expr) - if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => - { + if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => { // Just check for errors and recover; do not eat semicolon yet. - if let Err(mut e) = - self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) - { - if let TokenKind::DocComment(..) = self.token.kind { - if let Ok(snippet) = self.span_to_snippet(self.token.span) { - let sp = self.token.span; - let marker = &snippet[..3]; - let (comment_marker, doc_comment_marker) = marker.split_at(2); - - e.span_suggestion( - sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), - &format!( - "add a space before `{}` to use a regular comment", - doc_comment_marker, - ), - format!("{} {}", comment_marker, doc_comment_marker), - Applicability::MaybeIncorrect, - ); + // `expect_one_of` returns PResult<'a, bool /* recovered */> + let replace_with_err = + match self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) { + // Recover from parser, skip type error to avoid extra errors. + Ok(true) => true, + Err(mut e) => { + if let TokenKind::DocComment(..) = self.token.kind && + let Ok(snippet) = self.span_to_snippet(self.token.span) { + let sp = self.token.span; + let marker = &snippet[..3]; + let (comment_marker, doc_comment_marker) = marker.split_at(2); + + e.span_suggestion( + sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), + &format!( + "add a space before `{}` to use a regular comment", + doc_comment_marker, + ), + format!("{} {}", comment_marker, doc_comment_marker), + Applicability::MaybeIncorrect, + ); } - } - if let Err(mut e) = - self.check_mistyped_turbofish_with_multiple_type_params(e, expr) - { - if recover.no() { - return Err(e); + + if let Err(mut e) = + self.check_mistyped_turbofish_with_multiple_type_params(e, expr) + { + if recover.no() { + return Err(e); + } + e.emit(); + self.recover_stmt(); } - e.emit(); - self.recover_stmt(); + true } - // Don't complain about type errors in body tail after parse error (#57383). + _ => false + }; + if replace_with_err { + // We already emitted an error, so don't emit another type error let sp = expr.span.to(self.prev_token.span); *expr = self.mk_expr_err(sp); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b19e85427e7..27a57adf964 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2062,7 +2062,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // so this lets us continue to run them while maintaining backwards compatibility. // In the long run, the checks should be harmonized. if let ItemKind::Macro(ref macro_def, _) = item.kind { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { check_non_exported_macro_for_invalid_attrs(self.tcx, item); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 6a97ad3fe86..753d01f46ca 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::middle::privacy::Level; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; @@ -280,8 +280,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } fn visit_node(&mut self, node: Node<'tcx>) { - if let Node::ImplItem(hir::ImplItem { def_id, .. }) = node - && self.should_ignore_item(def_id.to_def_id()) + if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node + && self.should_ignore_item(owner_id.to_def_id()) { return; } @@ -293,7 +293,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id); + let def = self.tcx.adt_def(item.owner_id); self.repr_has_repr_c = def.repr().c(); self.repr_has_repr_simd = def.repr().simd(); @@ -306,7 +306,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { - let item = self.tcx.local_parent(impl_item.def_id.def_id); + let item = self.tcx.local_parent(impl_item.owner_id.def_id); if self.tcx.impl_trait_ref(item).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static @@ -517,10 +517,10 @@ fn check_item<'tcx>( ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id()); if allow_dead_code { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } - match tcx.def_kind(id.def_id) { + match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { @@ -540,15 +540,15 @@ fn check_item<'tcx>( } } DefKind::Impl => { - let of_trait = tcx.impl_trait_ref(id.def_id); + let of_trait = tcx.impl_trait_ref(id.owner_id); if of_trait.is_some() { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } // get DefIds from another query let local_def_ids = tcx - .associated_item_def_ids(id.def_id) + .associated_item_def_ids(id.owner_id) .iter() .filter_map(|def_id| def_id.as_local()); @@ -566,12 +566,12 @@ fn check_item<'tcx>( if let hir::ItemKind::Struct(ref variant_data, _) = item.kind && let Some(ctor_hir_id) = variant_data.ctor_hir_id() { - struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id.def_id); + struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id); } } DefKind::GlobalAsm => { // global_asm! is always live. - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } _ => {} } @@ -579,12 +579,12 @@ fn check_item<'tcx>( fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) { use hir::TraitItemKind::{Const, Fn}; - if matches!(tcx.def_kind(id.def_id), DefKind::AssocConst | DefKind::AssocFn) { + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id()) { - worklist.push(trait_item.def_id.def_id); + worklist.push(trait_item.owner_id.def_id); } } } @@ -594,23 +594,23 @@ fn check_foreign_item<'tcx>( worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId, ) { - if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn) + if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn) && has_allow_dead_code_or_lang_attr(tcx, id.hir_id()) { - worklist.push(id.def_id.def_id); + worklist.push(id.owner_id.def_id); } } fn create_and_seed_worklist<'tcx>( tcx: TyCtxt<'tcx>, ) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); // see `MarkSymbolVisitor::struct_constructors` let mut struct_constructors = Default::default(); - let mut worklist = access_levels + let mut worklist = effective_visibilities .iter() .filter_map(|(&id, effective_vis)| { - effective_vis.is_public_at_level(AccessLevel::Reachable).then_some(id) + effective_vis.is_public_at_level(Level::Reachable).then_some(id) }) // Seed entry point .chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local())) @@ -861,19 +861,19 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if !live_symbols.contains(&item.def_id.def_id) { - let parent = tcx.local_parent(item.def_id.def_id); + if !live_symbols.contains(&item.owner_id.def_id) { + let parent = tcx.local_parent(item.owner_id.def_id); if parent != module && !live_symbols.contains(&parent) { // We already have diagnosed something. continue; } - visitor.check_definition(item.def_id.def_id); + visitor.check_definition(item.owner_id.def_id); continue; } - let def_kind = tcx.def_kind(item.def_id); + let def_kind = tcx.def_kind(item.owner_id); if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { - let adt = tcx.adt_def(item.def_id); + let adt = tcx.adt_def(item.owner_id); let mut dead_variants = Vec::new(); for variant in adt.variants() { @@ -917,7 +917,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { } visitor.warn_dead_fields_and_variants( - item.def_id.def_id, + item.owner_id.def_id, "constructed", dead_variants, false, @@ -926,11 +926,11 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { } for impl_item in module_items.impl_items() { - visitor.check_definition(impl_item.def_id.def_id); + visitor.check_definition(impl_item.owner_id.def_id); } for foreign_item in module_items.foreign_items() { - visitor.check_definition(foreign_item.def_id.def_id); + visitor.check_definition(foreign_item.owner_id.def_id); } // We do not warn trait items. diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 3f991cf6572..a72056e00b1 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -73,19 +73,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.trait_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.impl_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } for id in crate_items.foreign_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); + observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id); } diagnostic_items diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 38a259ca884..5885f45ae45 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -62,7 +62,7 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry } else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) { EntryPointType::RustcMainAttr } else { - if let Some(name) = ctxt.tcx.opt_item_name(id.def_id.to_def_id()) + if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id()) && name == sym::main { if at_root { // This is a top-level function so can be `main`. @@ -82,7 +82,7 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { - let at_root = ctxt.tcx.opt_local_parent(id.def_id.def_id) == Some(CRATE_DEF_ID); + let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); match entry_point_type(ctxt, id, at_root) { EntryPointType::None => { @@ -90,7 +90,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); } } - _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => { + _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { for attr in [sym::start, sym::rustc_main] { if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { ctxt.tcx.sess.emit_err(AttrOnlyInFunctions { span, attr }); @@ -102,16 +102,16 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { ctxt.tcx.sess.emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe }); } - ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id)); + ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); + ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.sess.emit_err(MultipleRustcMain { - span: ctxt.tcx.def_span(id.def_id.to_def_id()), + span: ctxt.tcx.def_span(id.owner_id.to_def_id()), first: ctxt.attr_main_fn.unwrap().1, - additional: ctxt.tcx.def_span(id.def_id.to_def_id()), + additional: ctxt.tcx.def_span(id.owner_id.to_def_id()), }); } } @@ -120,11 +120,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); } if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); + ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.sess.emit_err(MultipleStartFunctions { - span: ctxt.tcx.def_span(id.def_id), - labeled: ctxt.tcx.def_span(id.def_id.to_def_id()), + span: ctxt.tcx.def_span(id.owner_id), + labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()), previous: ctxt.start_fn.unwrap().1, }); } diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 3ee8c8bcb1d..88bb39debb1 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -126,7 +126,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { fn visit_item(&mut self, i: &'hir hir::Item<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i)); } fn visit_id(&mut self, hir_id: HirId) { @@ -148,16 +148,16 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_foreign_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i)); } fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_trait_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i)); } fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) { let mut inner_visitor = self.new_visitor(self.hir_map); - inner_visitor.check(i.def_id, |this| intravisit::walk_impl_item(this, i)); + inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i)); } } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 71b0735192a..df811be2a7e 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -217,9 +217,9 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.def_id)), id.hir_id()); + collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id()); - if matches!(tcx.def_kind(id.def_id), DefKind::Enum) { + if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(def, ..) = &item.kind { for variant in def.variants { diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index c1085094962..5322baee747 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -15,11 +15,11 @@ pub fn test_layout(tcx: TyCtxt<'_>) { // if the `rustc_attrs` feature is not enabled, don't bother testing layout for id in tcx.hir().items() { if matches!( - tcx.def_kind(id.def_id), + tcx.def_kind(id.owner_id), DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union ) { - for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) { - dump_layout_of(tcx, id.def_id.def_id, attr); + for attr in tcx.get_attrs(id.owner_id.to_def_id(), sym::rustc_layout) { + dump_layout_of(tcx, id.owner_id.def_id, attr); } } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 0f2879c1eff..10d5fc5d671 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; -use rustc_middle::middle::privacy::{self, AccessLevel}; +use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::config::CrateType; @@ -29,7 +29,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenF match item.kind { hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true, hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { - let generics = tcx.generics_of(item.def_id); + let generics = tcx.generics_of(item.owner_id); generics.requires_monomorphization(tcx) } _ => false, @@ -42,7 +42,7 @@ fn method_might_be_inlined( impl_src: LocalDefId, ) -> bool { let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id()); - let generics = tcx.generics_of(impl_item.def_id); + let generics = tcx.generics_of(impl_item.owner_id); if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true; } @@ -216,7 +216,7 @@ impl<'tcx> ReachableContext<'tcx> { if item_might_be_inlined( self.tcx, &item, - self.tcx.codegen_fn_attrs(item.def_id), + self.tcx.codegen_fn_attrs(item.owner_id), ) { self.visit_nested_body(body); } @@ -303,13 +303,13 @@ fn check_item<'tcx>( tcx: TyCtxt<'tcx>, id: hir::ItemId, worklist: &mut Vec<LocalDefId>, - access_levels: &privacy::AccessLevels, + effective_visibilities: &privacy::EffectiveVisibilities, ) { - if has_custom_linkage(tcx, id.def_id.def_id) { - worklist.push(id.def_id.def_id); + if has_custom_linkage(tcx, id.owner_id.def_id) { + worklist.push(id.owner_id.def_id); } - if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) { + if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { return; } @@ -318,8 +318,8 @@ fn check_item<'tcx>( if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = item.kind { - if !access_levels.is_reachable(item.def_id.def_id) { - worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id.def_id)); + if !effective_visibilities.is_reachable(item.owner_id.def_id) { + worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id)); let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { unreachable!(); @@ -354,7 +354,7 @@ fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { } fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { - let access_levels = &tcx.privacy_access_levels(()); + let effective_visibilities = &tcx.effective_visibilities(()); let any_library = tcx.sess.crate_types().iter().any(|ty| { @@ -373,10 +373,10 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { // If other crates link to us, they're going to expect to be able to // use the lang items, so we need to be sure to mark them as // exported. - reachable_context.worklist = access_levels + reachable_context.worklist = effective_visibilities .iter() .filter_map(|(&id, effective_vis)| { - effective_vis.is_public_at_level(AccessLevel::ReachableFromImplTrait).then_some(id) + effective_vis.is_public_at_level(Level::ReachableThroughImplTrait).then_some(id) }) .collect::<Vec<_>>(); @@ -399,12 +399,12 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - check_item(tcx, id, &mut reachable_context.worklist, access_levels); + check_item(tcx, id, &mut reachable_context.worklist, effective_visibilities); } for id in crate_items.impl_items() { - if has_custom_linkage(tcx, id.def_id.def_id) { - reachable_context.worklist.push(id.def_id.def_id); + if has_custom_linkage(tcx, id.owner_id.def_id) { + reachable_context.worklist.push(id.owner_id.def_id); } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9591aeb881f..78afa2f25f8 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -20,7 +20,7 @@ use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index}; use rustc_middle::ty::{query::Providers, TyCtxt}; use rustc_session::lint; @@ -378,7 +378,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } self.annotate( - i.def_id.def_id, + i.owner_id.def_id, i.span, fn_sig, kind, @@ -397,7 +397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ti.def_id.def_id, + ti.owner_id.def_id, ti.span, fn_sig, AnnotationKind::Required, @@ -420,7 +420,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ii.def_id.def_id, + ii.owner_id.def_id, ii.span, fn_sig, kind, @@ -478,7 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { self.annotate( - i.def_id.def_id, + i.owner_id.def_id, i.span, None, AnnotationKind::Required, @@ -516,13 +516,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { struct MissingStabilityAnnotations<'tcx> { tcx: TyCtxt<'tcx>, - access_levels: &'tcx AccessLevels, + effective_visibilities: &'tcx EffectiveVisibilities, } impl<'tcx> MissingStabilityAnnotations<'tcx> { fn check_missing_stability(&self, def_id: LocalDefId, span: Span) { let stab = self.tcx.stability().local_stability(def_id); - if !self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(def_id) { + if !self.tcx.sess.opts.test + && stab.is_none() + && self.effective_visibilities.is_reachable(def_id) + { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); self.tcx.sess.emit_err(MissingStabilityAttr { span, descr }); } @@ -540,7 +543,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { .lookup_stability(def_id) .map_or(false, |stability| stability.level.is_stable()); let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); - let is_reachable = self.access_levels.is_reachable(def_id); + let is_reachable = self.effective_visibilities.is_reachable(def_id); if is_const && is_stable && missing_const_stability_attribute && is_reachable { let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); @@ -566,25 +569,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) | hir::ItemKind::ForeignMod { .. } ) { - self.check_missing_stability(i.def_id.def_id, i.span); + self.check_missing_stability(i.owner_id.def_id, i.span); } // Ensure stable `const fn` have a const stability attribute. - self.check_missing_const_stability(i.def_id.def_id, i.span); + self.check_missing_const_stability(i.owner_id.def_id, i.span); intravisit::walk_item(self, i) } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - self.check_missing_stability(ti.def_id.def_id, ti.span); + self.check_missing_stability(ti.owner_id.def_id, ti.span); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.def_id.def_id, ii.span); - self.check_missing_const_stability(ii.def_id.def_id, ii.span); + self.check_missing_stability(ii.owner_id.def_id, ii.span); + self.check_missing_const_stability(ii.owner_id.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } @@ -603,7 +606,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { - self.check_missing_stability(i.def_id.def_id, i.span); + self.check_missing_stability(i.owner_id.def_id, i.span); intravisit::walk_foreign_item(self, i); } // Note that we don't need to `check_missing_stability` for default generic parameters, @@ -709,7 +712,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { return; } - let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id.def_id) else { + let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.owner_id.def_id) else { return; }; let def_id = cnum.as_def_id(); @@ -762,7 +765,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } for impl_item_ref in *items { - let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id); + let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id); if let Some(def_id) = impl_item.trait_item_def_id { // Pass `None` to skip deprecation warnings. @@ -919,8 +922,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let is_staged_api = tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api; if is_staged_api { - let access_levels = &tcx.privacy_access_levels(()); - let mut missing = MissingStabilityAnnotations { tcx, access_levels }; + let effective_visibilities = &tcx.effective_visibilities(()); + let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities }; missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); tcx.hir().walk_toplevel_module(&mut missing); tcx.hir().visit_all_item_likes_in_crate(&mut missing); diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 92024989a75..959ee600c07 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -34,7 +34,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem items.missing.push(item); } } else { - let span = tcx.def_span(id.def_id); + let span = tcx.def_span(id.owner_id); tcx.sess.emit_err(UnknownExternLangItem { span, lang_item }); } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2636db6dbe1..865d6306bd3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -23,7 +23,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; +use rustc_middle::middle::privacy::{EffectiveVisibilities, Level}; use rustc_middle::span_bug; use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode}; use rustc_middle::ty::query::Providers; @@ -310,7 +310,7 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib struct FindMin<'a, 'tcx, VL: VisibilityLike> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, min: VL, } @@ -344,8 +344,12 @@ trait VisibilityLike: Sized { // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to // associated types for which we can't determine visibility precisely. - fn of_impl(def_id: LocalDefId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self { - let mut find = FindMin { tcx, access_levels, min: Self::MAX }; + fn of_impl( + def_id: LocalDefId, + tcx: TyCtxt<'_>, + effective_visibilities: &EffectiveVisibilities, + ) -> Self { + let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX }; find.visit(tcx.type_of(def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { find.visit_trait(trait_ref); @@ -359,8 +363,8 @@ impl VisibilityLike for ty::Visibility { min(find.tcx.local_visibility(def_id), find.min, find.tcx) } } -impl VisibilityLike for Option<AccessLevel> { - const MAX: Self = Some(AccessLevel::Public); +impl VisibilityLike for Option<Level> { + const MAX: Self = Some(Level::Direct); // Type inference is very smart sometimes. // It can make an impl reachable even some components of its type or trait are unreachable. // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }` @@ -372,7 +376,7 @@ impl VisibilityLike for Option<AccessLevel> { // (which require reaching the `DefId`s in them). const SHALLOW: bool = true; fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self { - cmp::min(find.access_levels.get_access_level(def_id), find.min) + cmp::min(find.effective_visibilities.public_at_level(def_id), find.min) } } @@ -383,8 +387,8 @@ impl VisibilityLike for Option<AccessLevel> { struct EmbargoVisitor<'tcx> { tcx: TyCtxt<'tcx>, - /// Accessibility levels for reachable nodes. - access_levels: AccessLevels, + /// Effective visibilities for reachable nodes. + effective_visibilities: EffectiveVisibilities, /// A set of pairs corresponding to modules, where the first module is /// reachable via a macro that's defined in the second module. This cannot /// be represented as reachable because it can't handle the following case: @@ -398,38 +402,34 @@ struct EmbargoVisitor<'tcx> { /// n::p::f() /// } macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>, - /// Previous accessibility level; `None` means unreachable. - prev_level: Option<AccessLevel>, + /// Previous visibility level; `None` means unreachable. + prev_level: Option<Level>, /// Has something changed in the level map? changed: bool, } struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> { - access_level: Option<AccessLevel>, + level: Option<Level>, item_def_id: LocalDefId, ev: &'a mut EmbargoVisitor<'tcx>, } impl<'tcx> EmbargoVisitor<'tcx> { - fn get(&self, def_id: LocalDefId) -> Option<AccessLevel> { - self.access_levels.get_access_level(def_id) + fn get(&self, def_id: LocalDefId) -> Option<Level> { + self.effective_visibilities.public_at_level(def_id) } - fn update_with_hir_id( - &mut self, - hir_id: hir::HirId, - level: Option<AccessLevel>, - ) -> Option<AccessLevel> { + fn update_with_hir_id(&mut self, hir_id: hir::HirId, level: Option<Level>) -> Option<Level> { let def_id = self.tcx.hir().local_def_id(hir_id); self.update(def_id, level) } /// Updates node level and returns the updated level. - fn update(&mut self, def_id: LocalDefId, level: Option<AccessLevel>) -> Option<AccessLevel> { + fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> { let old_level = self.get(def_id); - // Accessibility levels can only grow. + // Visibility levels can only grow. if level > old_level { - self.access_levels.set_access_level( + self.effective_visibilities.set_public_at_level( def_id, || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)), level.unwrap(), @@ -444,10 +444,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { fn reach( &mut self, def_id: LocalDefId, - access_level: Option<AccessLevel>, + level: Option<Level>, ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { ReachEverythingInTheInterfaceVisitor { - access_level: cmp::min(access_level, Some(AccessLevel::Reachable)), + level: cmp::min(level, Some(Level::Reachable)), item_def_id: def_id, ev: self, } @@ -505,9 +505,9 @@ impl<'tcx> EmbargoVisitor<'tcx> { fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) { let module = self.tcx.hir().get_module(module_def_id).0; for item_id in module.item_ids { - let def_kind = self.tcx.def_kind(item_id.def_id); - let vis = self.tcx.local_visibility(item_id.def_id.def_id); - self.update_macro_reachable_def(item_id.def_id.def_id, def_kind, vis, defining_mod); + let def_kind = self.tcx.def_kind(item_id.owner_id); + let vis = self.tcx.local_visibility(item_id.owner_id.def_id); + self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod); } if let Some(exports) = self.tcx.module_reexports(module_def_id) { for export in exports { @@ -530,7 +530,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { vis: ty::Visibility, module: LocalDefId, ) { - let level = Some(AccessLevel::Reachable); + let level = Some(Level::Reachable); if vis.is_public() { self.update(def_id, level); } @@ -627,14 +627,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let item_level = match item.kind { hir::ItemKind::Impl { .. } => { - let impl_level = Option::<AccessLevel>::of_impl( - item.def_id.def_id, + let impl_level = Option::<Level>::of_impl( + item.owner_id.def_id, self.tcx, - &self.access_levels, + &self.effective_visibilities, ); - self.update(item.def_id.def_id, impl_level) + self.update(item.owner_id.def_id, impl_level) } - _ => self.get(item.def_id.def_id), + _ => self.get(item.owner_id.def_id), }; // Update levels of nested things. @@ -653,15 +653,15 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Impl(ref impl_) => { for impl_item_ref in impl_.items { if impl_.of_trait.is_some() - || self.tcx.visibility(impl_item_ref.id.def_id).is_public() + || self.tcx.visibility(impl_item_ref.id.owner_id).is_public() { - self.update(impl_item_ref.id.def_id.def_id, item_level); + self.update(impl_item_ref.id.owner_id.def_id, item_level); } } } hir::ItemKind::Trait(.., trait_item_refs) => { for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.def_id.def_id, item_level); + self.update(trait_item_ref.id.owner_id.def_id, item_level); } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { @@ -677,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Macro(ref macro_def, _) => { - self.update_reachability_from_macro(item.def_id.def_id, macro_def); + self.update_reachability_from_macro(item.owner_id.def_id, macro_def); } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - if self.tcx.visibility(foreign_item.id.def_id).is_public() { - self.update(foreign_item.id.def_id.def_id, item_level); + if self.tcx.visibility(foreign_item.id.owner_id).is_public() { + self.update(foreign_item.id.owner_id.def_id, item_level); } } } @@ -705,7 +705,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Handled in the access level of in rustc_resolve + // Handled in `rustc_resolve`. hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} @@ -718,9 +718,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // FIXME: This is some serious pessimization intended to workaround deficiencies // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time // reachable if they are returned via `impl Trait`, even from private functions. - let exist_level = - cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); - self.reach(item.def_id.def_id, exist_level).generics().predicates().ty(); + let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait)); + self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty(); } } // Visit everything. @@ -729,20 +728,20 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates().ty(); + self.reach(item.owner_id.def_id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., trait_item_refs) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { let tcx = self.tcx; - let mut reach = self.reach(trait_item_ref.id.def_id.def_id, item_level); + let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type - && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value() + && !tcx.impl_defaultness(trait_item_ref.id.owner_id).has_value() { // No type to visit. } else { @@ -753,22 +752,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); } } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level) + self.reach(item.owner_id.def_id, item_level) .generics() .predicates() .ty() .trait_ref(); for impl_item_ref in impl_.items { - let impl_item_level = self.get(impl_item_ref.id.def_id.def_id); + let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id); if impl_item_level.is_some() { - self.reach(impl_item_ref.id.def_id.def_id, impl_item_level) + self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level) .generics() .predicates() .ty(); @@ -780,7 +779,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); } for variant in def.variants { let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); @@ -791,13 +790,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.reach(item.def_id.def_id, variant_level).ty(); + self.reach(item.owner_id.def_id, variant_level).ty(); } if let Some(hir_id) = variant.data.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id.def_id, ctor_level).ty(); + self.reach(item.owner_id.def_id, ctor_level).ty(); } } } @@ -805,9 +804,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - let foreign_item_level = self.get(foreign_item.id.def_id.def_id); + let foreign_item_level = self.get(foreign_item.id.owner_id.def_id); if foreign_item_level.is_some() { - self.reach(foreign_item.id.def_id.def_id, foreign_item_level) + self.reach(foreign_item.id.owner_id.def_id, foreign_item_level) .generics() .predicates() .ty(); @@ -817,7 +816,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.def_id.def_id, item_level).generics().predicates(); + self.reach(item.owner_id.def_id, item_level).generics().predicates(); for field in struct_def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); let field_level = self.get(def_id); @@ -830,7 +829,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id.def_id, ctor_level).ty(); + self.reach(item.owner_id.def_id, ctor_level).ty(); } } } @@ -901,10 +900,10 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> _descr: &dyn fmt::Display, ) -> ControlFlow<Self::BreakTy> { if let Some(def_id) = def_id.as_local() { - if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) = - (self.tcx().visibility(def_id.to_def_id()), self.access_level) + if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) = + (self.tcx().visibility(def_id.to_def_id()), self.level) { - self.ev.update(def_id, self.access_level); + self.ev.update(def_id, self.level); } } ControlFlow::CONTINUE @@ -912,21 +911,21 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> } //////////////////////////////////////////////////////////////////////////////// -/// Visitor, used for AccessLevels table checking +/// Visitor, used for EffectiveVisibilities table checking //////////////////////////////////////////////////////////////////////////////// pub struct TestReachabilityVisitor<'tcx, 'a> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, } impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { - fn access_level_diagnostic(&mut self, def_id: LocalDefId) { + fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) { - if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) { - let mut error_msg = String::new(); - let span = self.tcx.def_span(def_id.to_def_id()); - for level in AccessLevel::all_levels() { - let vis_str = match effective_vis.get(level) { + let mut error_msg = String::new(); + let span = self.tcx.def_span(def_id.to_def_id()); + if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { + for level in Level::all_levels() { + let vis_str = match effective_vis.at_level(level) { ty::Visibility::Restricted(restricted_id) => { if restricted_id.is_top_level_module() { "pub(crate)".to_string() @@ -938,36 +937,38 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { } ty::Visibility::Public => "pub".to_string(), }; - if level != AccessLevel::Public { + if level != Level::Direct { error_msg.push_str(", "); } error_msg.push_str(&format!("{:?}: {}", level, vis_str)); } - self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); + } else { + error_msg.push_str("not in the table"); } + self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg }); } } } impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); match item.kind { hir::ItemKind::Enum(ref def, _) => { for variant in def.variants.iter() { let variant_id = self.tcx.hir().local_def_id(variant.id); - self.access_level_diagnostic(variant_id); + self.effective_visibility_diagnostic(variant_id); for field in variant.data.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); - self.access_level_diagnostic(def_id); + self.effective_visibility_diagnostic(def_id); } } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { for field in def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); - self.access_level_diagnostic(def_id); + self.effective_visibility_diagnostic(def_id); } } _ => {} @@ -975,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - self.access_level_diagnostic(item.def_id.def_id); + self.effective_visibility_diagnostic(item.owner_id.def_id); } } @@ -1052,7 +1053,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { // Don't visit nested modules, since we run a separate visitor walk - // for each module in `privacy_access_levels` + // for each module in `effective_visibilities` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -1064,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; } @@ -1177,7 +1178,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { // Don't visit nested modules, since we run a separate visitor walk - // for each module in `privacy_access_levels` + // for each module in `effective_visibilities` } fn visit_nested_body(&mut self, body: hir::BodyId) { @@ -1367,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); let old_maybe_typeck_results = self.maybe_typeck_results.take(); intravisit::walk_item(self, item); self.maybe_typeck_results = old_maybe_typeck_results; @@ -1402,7 +1403,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - access_levels: &'a AccessLevels, + effective_visibilities: &'a EffectiveVisibilities, in_variant: bool, // Set of errors produced by this obsolete visitor. old_error_set: HirIdSet, @@ -1445,7 +1446,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { fn trait_is_public(&self, trait_id: LocalDefId) -> bool { // FIXME: this would preferably be using `exported_items`, but all // traits are exported currently (see `EmbargoVisitor.exported_trait`). - self.access_levels.is_public(trait_id) + self.effective_visibilities.is_directly_public(trait_id) } fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) { @@ -1457,7 +1458,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn item_is_public(&self, def_id: LocalDefId) -> bool { - self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public() + self.effective_visibilities.is_reachable(def_id) || self.tcx.visibility(def_id).is_public() } } @@ -1511,7 +1512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::Trait(.., bounds, _) => { - if !self.trait_is_public(item.def_id.def_id) { + if !self.trait_is_public(item.owner_id.def_id) { return; } @@ -1571,9 +1572,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { || impl_.items.iter().any(|impl_item_ref| { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { - self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) - } + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => self + .effective_visibilities + .is_reachable(impl_item_ref.id.owner_id.def_id), hir::ImplItemKind::Type(_) => false, } }); @@ -1592,7 +1593,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.def_id) => + if self.item_is_public(impl_item.owner_id.def_id) => { intravisit::walk_impl_item(self, impl_item) } @@ -1633,8 +1634,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) - || self.tcx.visibility(impl_item_ref.id.def_id).is_public() + if self + .effective_visibilities + .is_reachable(impl_item_ref.id.owner_id.def_id) + || self.tcx.visibility(impl_item_ref.id.owner_id).is_public() { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { @@ -1662,7 +1665,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.def_id) => { + _ if !self.item_is_public(item.owner_id.def_id) => { return; } @@ -1693,7 +1696,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - if self.access_levels.is_reachable(item.def_id.def_id) { + if self.effective_visibilities.is_reachable(item.owner_id.def_id) { intravisit::walk_foreign_item(self, item) } } @@ -1708,7 +1711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - if self.access_levels.is_reachable(self.tcx.hir().local_def_id(v.id)) { + if self.effective_visibilities.is_reachable(self.tcx.hir().local_def_id(v.id)) { self.in_variant = true; intravisit::walk_variant(self, v); self.in_variant = false; @@ -1930,7 +1933,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; - let def_id = id.def_id.def_id; + let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); let def_kind = tcx.def_kind(def_id); @@ -1946,17 +1949,17 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Trait => { let item = tcx.hir().item(id); if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { self.check_assoc_item( - trait_item_ref.id.def_id.def_id, + trait_item_ref.id.owner_id.def_id, trait_item_ref.kind, item_visibility, ); if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.def_id.def_id, item_visibility).bounds(); + self.check(trait_item_ref.id.owner_id.def_id, item_visibility).bounds(); } } } @@ -1967,7 +1970,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref def, _) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for variant in def.variants { for field in variant.data.fields() { @@ -1982,8 +1985,11 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { for foreign_item in items { - let vis = tcx.local_visibility(foreign_item.id.def_id.def_id); - self.check(foreign_item.id.def_id.def_id, vis).generics().predicates().ty(); + let vis = tcx.local_visibility(foreign_item.id.owner_id.def_id); + self.check(foreign_item.id.owner_id.def_id, vis) + .generics() + .predicates() + .ty(); } } } @@ -1993,7 +1999,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { - self.check(item.def_id.def_id, item_visibility).generics().predicates(); + self.check(item.owner_id.def_id, item_visibility).generics().predicates(); for field in struct_def.fields() { let def_id = tcx.hir().local_def_id(field.hir_id); @@ -2010,20 +2016,24 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::Impl(ref impl_) = item.kind { let impl_vis = - ty::Visibility::of_impl(item.def_id.def_id, tcx, &Default::default()); + ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default()); // check that private components do not appear in the generics or predicates of inherent impls // this check is intentionally NOT performed for impls of traits, per #90586 if impl_.of_trait.is_none() { - self.check(item.def_id.def_id, impl_vis).generics().predicates(); + self.check(item.owner_id.def_id, impl_vis).generics().predicates(); } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { - min(tcx.local_visibility(impl_item_ref.id.def_id.def_id), impl_vis, tcx) + min( + tcx.local_visibility(impl_item_ref.id.owner_id.def_id), + impl_vis, + tcx, + ) } else { impl_vis }; self.check_assoc_item( - impl_item_ref.id.def_id.def_id, + impl_item_ref.id.owner_id.def_id, impl_item_ref.kind, impl_item_vis, ); @@ -2038,7 +2048,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn provide(providers: &mut Providers) { *providers = Providers { visibility, - privacy_access_levels, + effective_visibilities, check_private_in_public, check_mod_privacy, ..*providers @@ -2110,14 +2120,14 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { intravisit::walk_mod(&mut visitor, module, hir_id); } -fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { +fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { // Build up a set of all exported items in the AST. This is a set of all // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { tcx, - access_levels: tcx.resolutions(()).access_levels.clone(), + effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(), macro_reachable: Default::default(), - prev_level: Some(AccessLevel::Public), + prev_level: Some(Level::Direct), changed: false, }; @@ -2130,18 +2140,19 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { } } - let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels }; + let mut check_visitor = + TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities }; tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor); - tcx.arena.alloc(visitor.access_levels) + tcx.arena.alloc(visitor.effective_visibilities) } fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { - let access_levels = tcx.privacy_access_levels(()); + let effective_visibilities = tcx.effective_visibilities(()); let mut visitor = ObsoleteVisiblePrivateTypesVisitor { tcx, - access_levels, + effective_visibilities, in_variant: false, old_error_set: Default::default(), }; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index a5921650112..8b14ce210a2 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1,8 +1,9 @@ use crate::QueryCtxt; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock}; use rustc_data_structures::unhash::UnhashMap; +use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; @@ -792,7 +793,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId { } } -impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> { +impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId> { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { RefDecodable::decode(d) } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 257784341e3..c40669ac95b 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -6,55 +6,54 @@ use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::middle::privacy::Level; use rustc_middle::ty::{DefIdTree, Visibility}; -pub struct AccessLevelsVisitor<'r, 'a> { +pub struct EffectiveVisibilitiesVisitor<'r, 'a> { r: &'r mut Resolver<'a>, changed: bool, } -impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { - /// Fills the `Resolver::access_levels` table with public & exported items +impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> { + /// Fills the `Resolver::effective_visibilities` table with public & exported items /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. - pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { - let mut visitor = AccessLevelsVisitor { r, changed: false }; + pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { + let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false }; - visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, AccessLevel::Public); - visitor.set_bindings_access_level(CRATE_DEF_ID); + visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct); + visitor.set_bindings_effective_visibilities(CRATE_DEF_ID); while visitor.changed { visitor.reset(); visit::walk_crate(&mut visitor, krate); } - info!("resolve::access_levels: {:#?}", r.access_levels); + info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities); } fn reset(&mut self) { self.changed = false; } - /// Update the access level of the bindings in the given module accordingly. The module access - /// level has to be Exported or Public. - /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level). - fn set_bindings_access_level(&mut self, module_id: LocalDefId) { + /// Update effective visibilities of bindings in the given module, + /// including their whole reexport chains. + fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { assert!(self.r.module_map.contains_key(&&module_id.to_def_id())); let module = self.r.get_module(module_id.to_def_id()).unwrap(); let resolutions = self.r.resolutions(module); for (_, name_resolution) in resolutions.borrow().iter() { if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() { - // Set the given binding access level to `AccessLevel::Public` and - // sets the rest of the `use` chain to `AccessLevel::Exported` until + // Set the given effective visibility level to `Level::Direct` and + // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. // FIXME: tag and is_public() condition should be removed, but assertions occur. - let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public }; + let tag = if binding.is_import() { Level::Reexported } else { Level::Direct }; if binding.vis.is_public() { let mut prev_parent_id = module_id; - let mut level = AccessLevel::Public; + let mut level = Level::Direct; while let NameBindingKind::Import { binding: nested_binding, import, .. } = binding.kind { @@ -76,7 +75,7 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { update(additional_ids.1); } - level = AccessLevel::Exported; + level = Level::Reexported; prev_parent_id = self.r.local_def_id(import.id); binding = nested_binding; } @@ -94,12 +93,20 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { def_id: LocalDefId, nominal_vis: Visibility, parent_id: LocalDefId, - tag: AccessLevel, + tag: Level, ) { - let mut access_levels = std::mem::take(&mut self.r.access_levels); - let module_id = - self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local(); - let res = access_levels.update( + let module_id = self + .r + .get_nearest_non_block_module(def_id.to_def_id()) + .nearest_parent_mod() + .expect_local(); + if nominal_vis == Visibility::Restricted(module_id) + || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id) + { + return; + } + let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities); + self.changed |= effective_visibilities.update( def_id, nominal_vis, || Visibility::Restricted(module_id), @@ -107,22 +114,14 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { tag, &*self.r, ); - if let Ok(changed) = res { - self.changed |= changed; - } else { - self.r.session.delay_span_bug( - self.r.opt_span(def_id.to_def_id()).unwrap(), - "Can't update effective visibility", - ); - } - self.r.access_levels = access_levels; + self.r.effective_visibilities = effective_visibilities; } } -impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { +impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> { fn visit_item(&mut self, item: &'ast ast::Item) { let def_id = self.r.local_def_id(item.id); - // Set access level of nested items. + // Update effective visibilities of nested items. // If it's a mod, also make the visitor walk all of its items match item.kind { // Resolved in rustc_privacy when types are available @@ -136,29 +135,29 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { // Foreign modules inherit level from parents. ast::ItemKind::ForeignMod(..) => { let parent_id = self.r.local_parent(def_id); - self.update(def_id, Visibility::Public, parent_id, AccessLevel::Public); + self.update(def_id, Visibility::Public, parent_id, Level::Direct); } // Only exported `macro_rules!` items are public, but they always are ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => { let parent_id = self.r.local_parent(def_id); let vis = self.r.visibilities[&def_id]; - self.update(def_id, vis, parent_id, AccessLevel::Public); + self.update(def_id, vis, parent_id, Level::Direct); } ast::ItemKind::Mod(..) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); visit::walk_item(self, item); } ast::ItemKind::Enum(EnumDef { ref variants }, _) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); for field in variant.data.fields() { let field_def_id = self.r.local_def_id(field.id); let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, variant_def_id, AccessLevel::Public); + self.update(field_def_id, vis, variant_def_id, Level::Direct); } } } @@ -167,12 +166,12 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { for field in def.fields() { let field_def_id = self.r.local_def_id(field.id); let vis = self.r.visibilities[&field_def_id]; - self.update(field_def_id, vis, def_id, AccessLevel::Public); + self.update(field_def_id, vis, def_id, Level::Direct); } } ast::ItemKind::Trait(..) => { - self.set_bindings_access_level(def_id); + self.set_bindings_effective_visibilities(def_id); } ast::ItemKind::ExternCrate(..) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 58853346a92..00eb768ad18 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -30,6 +30,7 @@ use rustc_span::{BytePos, Span}; use smallvec::{smallvec, SmallVec}; use rustc_span::source_map::{respan, Spanned}; +use std::assert_matches::debug_assert_matches; use std::collections::{hash_map::Entry, BTreeSet}; use std::mem::{replace, take}; @@ -568,7 +569,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// They will be used to determine the correct lifetime for the fn return type. /// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named /// lifetimes. - lifetime_elision_candidates: Option<FxIndexMap<LifetimeRes, LifetimeElisionCandidate>>, + lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>, /// The trait that the current context can refer to. current_trait_ref: Option<(Module<'a>, TraitRef)>, @@ -1802,7 +1803,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match res { LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { - candidates.insert(res, candidate); + candidates.push((res, candidate)); } } LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} @@ -1855,12 +1856,25 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { has_self: bool, inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>, ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> { - let outer_candidates = - replace(&mut self.lifetime_elision_candidates, Some(Default::default())); + enum Elision { + /// We have not found any candidate. + None, + /// We have a candidate bound to `self`. + Self_(LifetimeRes), + /// We have a candidate bound to a parameter. + Param(LifetimeRes), + /// We failed elision. + Err, + } - let mut elision_lifetime = None; - let mut lifetime_count = 0; + // Save elision state to reinstate it later. + let outer_candidates = self.lifetime_elision_candidates.take(); + + // Result of elision. + let mut elision_lifetime = Elision::None; + // Information for diagnostics. let mut parameter_info = Vec::new(); + let mut all_candidates = Vec::new(); let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; for (index, (pat, ty)) in inputs.enumerate() { @@ -1870,12 +1884,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); } }); + + // Record elision candidates only for this parameter. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = Some(Default::default()); self.visit_ty(ty); + let local_candidates = self.lifetime_elision_candidates.take(); - if let Some(ref candidates) = self.lifetime_elision_candidates { - let new_count = candidates.len(); - let local_count = new_count - lifetime_count; - if local_count != 0 { + if let Some(candidates) = local_candidates { + let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect(); + let lifetime_count = distinct.len(); + if lifetime_count != 0 { parameter_info.push(ElisionFnParameter { index, ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind { @@ -1883,48 +1902,64 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } else { None }, - lifetime_count: local_count, + lifetime_count, span: ty.span, }); + all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| { + match candidate { + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => { + None + } + LifetimeElisionCandidate::Missing(missing) => Some(missing), + } + })); + } + let mut distinct_iter = distinct.into_iter(); + if let Some(res) = distinct_iter.next() { + match elision_lifetime { + // We are the first parameter to bind lifetimes. + Elision::None => { + if distinct_iter.next().is_none() { + // We have a single lifetime => success. + elision_lifetime = Elision::Param(res) + } else { + // We have have multiple lifetimes => error. + elision_lifetime = Elision::Err; + } + } + // We have 2 parameters that bind lifetimes => error. + Elision::Param(_) => elision_lifetime = Elision::Err, + // `self` elision takes precedence over everything else. + Elision::Self_(_) | Elision::Err => {} + } } - lifetime_count = new_count; } // Handle `self` specially. if index == 0 && has_self { let self_lifetime = self.find_lifetime_for_self(ty); if let Set1::One(lifetime) = self_lifetime { - elision_lifetime = Some(lifetime); - self.lifetime_elision_candidates = None; + // We found `self` elision. + elision_lifetime = Elision::Self_(lifetime); } else { - self.lifetime_elision_candidates = Some(Default::default()); - lifetime_count = 0; + // We do not have `self` elision: disregard the `Elision::Param` that we may + // have found. + elision_lifetime = Elision::None; } } debug!("(resolving function / closure) recorded parameter"); } - let all_candidates = replace(&mut self.lifetime_elision_candidates, outer_candidates); - debug!(?all_candidates); + // Reinstate elision state. + debug_assert_matches!(self.lifetime_elision_candidates, None); + self.lifetime_elision_candidates = outer_candidates; - if let Some(res) = elision_lifetime { + if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime { return Ok(res); } - // We do not have a `self` candidate, look at the full list. - let all_candidates = all_candidates.unwrap(); - if all_candidates.len() == 1 { - Ok(*all_candidates.first().unwrap().0) - } else { - let all_candidates = all_candidates - .into_iter() - .filter_map(|(_, candidate)| match candidate { - LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => None, - LifetimeElisionCandidate::Missing(missing) => Some(missing), - }) - .collect(); - Err((all_candidates, parameter_info)) - } + // We do not have a candidate. + Err((all_candidates, parameter_info)) } /// List all the lifetimes that appear in the provided type. @@ -2394,7 +2429,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Do not account for the parameters we just bound for function lifetime elision. if let Some(ref mut candidates) = self.lifetime_elision_candidates { for (_, res) in function_lifetime_rib.bindings.values() { - candidates.remove(res); + candidates.retain(|(r, _)| r != res); } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 850f023b1c1..7d5fe32ee28 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -784,10 +784,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return false; } err.code(rustc_errors::error_code!(E0411)); - err.span_label( - span, - "`Self` is only available in impls, traits, and type definitions".to_string(), - ); + err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { err.span_label( item_kind.ident.span, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1c1976af505..11b70a38da5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -7,6 +7,7 @@ //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(drain_filter)] #![feature(if_let_guard)] @@ -40,11 +41,12 @@ use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::span_bug; -use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs}; +use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn}; +use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_session::lint::LintBuffer; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -62,15 +64,15 @@ use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; -use crate::access_levels::AccessLevelsVisitor; +use crate::effective_visibilities::EffectiveVisibilitiesVisitor; type Res = def::Res<NodeId>; -mod access_levels; mod build_reduced_graph; mod check_unused; mod def_collector; mod diagnostics; +mod effective_visibilities; mod ident; mod imports; mod late; @@ -1029,7 +1031,7 @@ pub struct Resolver<'a> { proc_macros: Vec<NodeId>, confused_type_with_std_module: FxHashMap<Span, Span>, - access_levels: AccessLevels, + effective_visibilities: EffectiveVisibilities, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1333,7 +1335,7 @@ impl<'a> Resolver<'a> { trait_impls: Default::default(), proc_macros: Default::default(), confused_type_with_std_module: Default::default(), - access_levels: Default::default(), + effective_visibilities: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1376,9 +1378,7 @@ impl<'a> Resolver<'a> { Default::default() } - pub fn into_outputs( - self, - ) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) { + pub fn into_outputs(self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; let cstore = Box::new(self.crate_loader.into_cstore()); @@ -1393,13 +1393,14 @@ impl<'a> Resolver<'a> { let glob_map = self.glob_map; let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; - let access_levels = self.access_levels; - let resolutions = ResolverOutputs { + let effective_visibilities = self.effective_visibilities; + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span, expn_that_defined, visibilities, has_pub_restricted, - access_levels, + effective_visibilities, extern_crate_map, reexport_map, glob_map, @@ -1416,7 +1417,7 @@ impl<'a> Resolver<'a> { confused_type_with_std_module, registered_tools: self.registered_tools, }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, partial_res_map: self.partial_res_map, import_res_map: self.import_res_map, @@ -1429,16 +1430,15 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map, builtin_macro_kinds: self.builtin_macro_kinds, }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } - pub fn clone_outputs( - &self, - ) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) { + pub fn clone_outputs(&self) -> ResolverOutputs { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions.clone(); let cstore = Box::new(self.cstore().clone()); - let resolutions = ResolverOutputs { + let global_ctxt = ResolverGlobalCtxt { + cstore, source_span: self.source_span.clone(), expn_that_defined: self.expn_that_defined.clone(), visibilities: self.visibilities.clone(), @@ -1458,9 +1458,9 @@ impl<'a> Resolver<'a> { proc_macros, confused_type_with_std_module: self.confused_type_with_std_module.clone(), registered_tools: self.registered_tools.clone(), - access_levels: self.access_levels.clone(), + effective_visibilities: self.effective_visibilities.clone(), }; - let resolutions_lowering = ty::ResolverAstLowering { + let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args.clone(), partial_res_map: self.partial_res_map.clone(), import_res_map: self.import_res_map.clone(), @@ -1473,7 +1473,7 @@ impl<'a> Resolver<'a> { trait_map: self.trait_map.clone(), builtin_macro_kinds: self.builtin_macro_kinds.clone(), }; - (definitions, cstore, resolutions, resolutions_lowering) + ResolverOutputs { definitions, global_ctxt, ast_lowering } } fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { @@ -1521,8 +1521,8 @@ impl<'a> Resolver<'a> { pub fn resolve_crate(&mut self, krate: &Crate) { self.session.time("resolve_crate", || { self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports()); - self.session.time("resolve_access_levels", || { - AccessLevelsVisitor::compute_access_levels(self, krate) + self.session.time("compute_effective_visibilities", || { + EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate) }); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions()); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate)); diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 23d06d8e516..df5d992f663 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -57,7 +57,7 @@ macro_rules! access_from { ($save_ctxt:expr, $id:expr) => { Access { public: $save_ctxt.tcx.visibility($id).is_public(), - reachable: $save_ctxt.access_levels.is_reachable($id), + reachable: $save_ctxt.effective_visibilities.is_reachable($id), } }; } @@ -345,14 +345,14 @@ impl<'tcx> DumpVisitor<'tcx> { body: hir::BodyId, ) { let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { let body = map.body(body); if let Some(fn_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, DefData, item.span); 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.def_id.def_id), fn_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), fn_data); } for arg in decl.inputs { @@ -373,10 +373,10 @@ impl<'tcx> DumpVisitor<'tcx> { typ: &'tcx hir::Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) { - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.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.def_id.def_id), var_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), var_data); } v.visit_ty(&typ); v.visit_expr(expr); @@ -436,7 +436,7 @@ impl<'tcx> DumpVisitor<'tcx> { ) { debug!("process_struct {:?} {:?}", item, item.span); let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let kind = match item.kind { hir::ItemKind::Struct(_, _) => DefKind::Struct, @@ -473,10 +473,10 @@ 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.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind, - id: id_from_def_id(item.def_id.to_def_id()), + id: id_from_def_id(item.owner_id.to_def_id()), span, name, qualname: qualname.clone(), @@ -491,7 +491,7 @@ impl<'tcx> DumpVisitor<'tcx> { ); } - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { for field in def.fields() { v.process_struct_field_def(field, item.hir_id()); v.visit_ty(&field.ty); @@ -513,7 +513,7 @@ impl<'tcx> DumpVisitor<'tcx> { }; down_cast_data!(enum_data, DefData, item.span); - let access = access_from!(self.save_ctxt, item.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); for variant in enum_definition.variants { let name = variant.ident.name.to_string(); @@ -528,7 +528,7 @@ impl<'tcx> DumpVisitor<'tcx> { if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); let id = id_from_hir_id(variant.id, &self.save_ctxt); - let parent = Some(id_from_def_id(item.def_id.to_def_id())); + let parent = Some(id_from_def_id(item.owner_id.to_def_id())); let attrs = self.tcx.hir().attrs(variant.id); self.dumper.dump_def( @@ -566,7 +566,7 @@ impl<'tcx> DumpVisitor<'tcx> { if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); let id = id_from_hir_id(variant.id, &self.save_ctxt); - let parent = Some(id_from_def_id(item.def_id.to_def_id())); + let parent = Some(id_from_def_id(item.owner_id.to_def_id())); let attrs = self.tcx.hir().attrs(variant.id); self.dumper.dump_def( @@ -612,14 +612,14 @@ impl<'tcx> DumpVisitor<'tcx> { } let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id.def_id, |v| { + self.nest_typeck_results(item.owner_id.def_id, |v| { v.visit_ty(&impl_.self_ty); if let Some(trait_ref) = &impl_.of_trait { v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path)); } v.process_generic_params(&impl_.generics, "", item.hir_id()); for impl_item in impl_.items { - v.process_impl_item(map.impl_item(impl_item.id), item.def_id.to_def_id()); + v.process_impl_item(map.impl_item(impl_item.id), item.owner_id.to_def_id()); } }); } @@ -632,7 +632,7 @@ impl<'tcx> DumpVisitor<'tcx> { methods: &'tcx [hir::TraitItemRef], ) { let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let mut val = name.clone(); if !generics.params.is_empty() { val.push_str(&generic_params_to_string(generics.params)); @@ -642,13 +642,13 @@ impl<'tcx> DumpVisitor<'tcx> { val.push_str(&bounds_to_string(trait_refs)); } if !self.span.filter_generated(item.ident.span) { - let id = id_from_def_id(item.def_id.to_def_id()); + let id = id_from_def_id(item.owner_id.to_def_id()); let span = self.span_from_span(item.ident.span); let children = - methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); + methods.iter().map(|i| id_from_def_id(i.id.owner_id.to_def_id())).collect(); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind: DefKind::Trait, id, @@ -692,7 +692,7 @@ impl<'tcx> DumpVisitor<'tcx> { kind: RelationKind::SuperTrait, span, from: id_from_def_id(id), - to: id_from_def_id(item.def_id.to_def_id()), + to: id_from_def_id(item.owner_id.to_def_id()), }); } } @@ -702,7 +702,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_generic_params(generics, &qualname, item.hir_id()); for method in methods { let map = self.tcx.hir(); - self.process_trait_item(map.trait_item(method.id), item.def_id.to_def_id()) + self.process_trait_item(map.trait_item(method.id), item.owner_id.to_def_id()) } } @@ -710,7 +710,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.def_id.def_id), mod_data); + self.dumper.dump_def(&access_from!(self.save_ctxt, item.owner_id.def_id), mod_data); } } @@ -981,7 +981,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = body.map(|b| self.tcx.hir().body(b).value); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.process_assoc_const( - trait_item.def_id.def_id, + trait_item.owner_id.def_id, trait_item.ident, &ty, body, @@ -995,7 +995,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, body, - trait_item.def_id.def_id, + trait_item.owner_id.def_id, trait_item.ident, &trait_item.generics, trait_item.span, @@ -1005,11 +1005,11 @@ impl<'tcx> DumpVisitor<'tcx> { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = - format!("::{}", self.tcx.def_path_str(trait_item.def_id.to_def_id())); + format!("::{}", self.tcx.def_path_str(trait_item.owner_id.to_def_id())); if !self.span.filter_generated(trait_item.ident.span) { let span = self.span_from_span(trait_item.ident.span); - let id = id_from_def_id(trait_item.def_id.to_def_id()); + let id = id_from_def_id(trait_item.owner_id.to_def_id()); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.dumper.dump_def( @@ -1051,7 +1051,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = self.tcx.hir().body(body); let attrs = self.tcx.hir().attrs(impl_item.hir_id()); self.process_assoc_const( - impl_item.def_id.def_id, + impl_item.owner_id.def_id, impl_item.ident, &ty, Some(&body.value), @@ -1063,7 +1063,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, Some(body), - impl_item.def_id.def_id, + impl_item.owner_id.def_id, impl_item.ident, &impl_item.generics, impl_item.span, @@ -1088,7 +1088,7 @@ impl<'tcx> DumpVisitor<'tcx> { let filename = sm.span_to_filename(krate_mod.spans.inner_span); let data_id = id_from_hir_id(id, &self.save_ctxt); let children = - krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); + krate_mod.item_ids.iter().map(|i| id_from_def_id(i.owner_id.to_def_id())).collect(); let span = self.span_from_span(krate_mod.spans.inner_span); let attrs = self.tcx.hir().attrs(id); @@ -1137,10 +1137,10 @@ 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.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.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 = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &access, Import { @@ -1158,16 +1158,16 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::ItemKind::Use(path, hir::UseKind::Glob) => { // Make a comma-separated list of names of imported modules. - let names = self.tcx.names_imported_by_glob_use(item.def_id.def_id); + let names = self.tcx.names_imported_by_glob_use(item.owner_id.def_id); let names: Vec<_> = names.iter().map(|n| n.to_string()).collect(); // Otherwise it's a span with wrong macro expansion info, which // 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.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &access, Import { @@ -1188,7 +1188,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let name_span = item.ident.span; if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id); self.dumper.import( &Access { public: false, reachable: false }, Import { @@ -1228,15 +1228,15 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { intravisit::walk_mod(self, m, item.hir_id()); } hir::ItemKind::TyAlias(ty, ref generics) => { - let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id())); + let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id())); let value = ty_to_string(&ty); if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); - let id = id_from_def_id(item.def_id.to_def_id()); + let id = id_from_def_id(item.owner_id.to_def_id()); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id.def_id), + &access_from!(self.save_ctxt, item.owner_id.def_id), Def { kind: DefKind::Type, id, @@ -1324,7 +1324,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); - self.nest_typeck_results(item_id.def_id.def_id, |v| v.visit_item(item)); + self.nest_typeck_results(item_id.owner_id.def_id, |v| v.visit_item(item)); } _ => intravisit::walk_ty(self, t), } @@ -1431,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.def_id.def_id); + let access = access_from!(self.save_ctxt, item.owner_id.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 aa000b7067b..d0155c908a2 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -26,7 +26,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string}; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::privacy::AccessLevels; +use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::{self, print::with_no_trimmed_paths, DefIdTree, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, Input, OutputType}; @@ -54,7 +54,7 @@ use rls_data::{ pub struct SaveContext<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, - access_levels: &'tcx AccessLevels, + effective_visibilities: &'tcx EffectiveVisibilities, span_utils: SpanUtils<'tcx>, config: Config, impl_counter: Cell<u32>, @@ -141,7 +141,7 @@ impl<'tcx> SaveContext<'tcx> { } pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let attrs = self.tcx.hir().attrs(item.hir_id()); match item.kind { @@ -205,7 +205,7 @@ impl<'tcx> SaveContext<'tcx> { } pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> { - let def_id = item.def_id.to_def_id(); + let def_id = item.owner_id.to_def_id(); let attrs = self.tcx.hir().attrs(item.hir_id()); match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { @@ -297,7 +297,7 @@ impl<'tcx> SaveContext<'tcx> { children: m .item_ids .iter() - .map(|i| id_from_def_id(i.def_id.to_def_id())) + .map(|i| id_from_def_id(i.owner_id.to_def_id())) .collect(), decl_id: None, docs: self.docs_for_attrs(attrs), @@ -363,7 +363,7 @@ impl<'tcx> SaveContext<'tcx> { parent: None, children: items .iter() - .map(|i| id_from_def_id(i.id.def_id.to_def_id())) + .map(|i| id_from_def_id(i.id.owner_id.to_def_id())) .collect(), docs: String::new(), sig: None, @@ -968,16 +968,16 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( info!("Dumping crate {}", cratename); // Privacy checking must be done outside of type inference; use a - // fallback in case the access levels couldn't have been correctly computed. - let access_levels = match tcx.sess.compile_status() { - Ok(..) => tcx.privacy_access_levels(()), - Err(..) => tcx.arena.alloc(AccessLevels::default()), + // fallback in case effective visibilities couldn't have been correctly computed. + let effective_visibilities = match tcx.sess.compile_status() { + Ok(..) => tcx.effective_visibilities(()), + Err(..) => tcx.arena.alloc(EffectiveVisibilities::default()), }; let save_ctxt = SaveContext { tcx, maybe_typeck_results: None, - access_levels: &access_levels, + effective_visibilities: &effective_visibilities, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), impl_counter: Cell::new(0), diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 62e9f6520fb..83c51d213be 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -337,7 +337,7 @@ impl<'hir> Sig for hir::Item<'hir> { } let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -359,7 +359,7 @@ impl<'hir> Sig for hir::Item<'hir> { let mut text = "const ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -428,7 +428,7 @@ impl<'hir> Sig for hir::Item<'hir> { let mut text = "mod ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -764,7 +764,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> { } let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; @@ -780,7 +780,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> { let mut text = "type ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { - id: id_from_def_id(self.def_id.to_def_id()), + id: id_from_def_id(self.owner_id.to_def_id()), start: offset + text.len(), end: offset + text.len() + name.len(), }]; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 842aa98bc9e..322c7104be4 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -558,7 +558,7 @@ impl Span { self.data_untracked().is_dummy() } - /// Returns `true` if this span comes from a macro or desugaring. + /// Returns `true` if this span comes from any kind of macro, desugaring or inlining. #[inline] pub fn from_expansion(self) -> bool { self.ctxt() != SyntaxContext::root() @@ -571,6 +571,12 @@ impl Span { matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo } + /// Returns `true` if this span comes from MIR inlining. + pub fn is_inlined(self) -> bool { + let outer_expn = self.ctxt().outer_expn_data(); + matches!(outer_expn.kind, ExpnKind::Inlined) + } + /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3fe79370c37..7f16da52b44 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1901,6 +1901,13 @@ impl fmt::Display for Symbol { } } +// takes advantage of `str::to_string` specialization +impl ToString for Symbol { + fn to_string(&self) -> String { + self.as_str().to_string() + } +} + impl<S: Encoder> Encodable<S> for Symbol { default fn encode(&self, s: &mut S) { s.emit_str(self.as_str()); diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index c8c6fe2bf85..150459ce0f5 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -26,19 +26,19 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.trait_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.impl_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } for id in crate_items.foreign_items() { - symbol_names.process_attrs(id.def_id.def_id); + symbol_names.process_attrs(id.owner_id.def_id); } }) } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 1b58c9b864e..a335f8e06bc 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -69,7 +69,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { let ty = self.resolve_vars_if_possible(ty); if !(param_env, ty).needs_infer() { - return ty.is_copy_modulo_regions(self.tcx.at(span), param_env); + return ty.is_copy_modulo_regions(self.tcx, param_env); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 84038625fb2..1de85e2f288 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -192,12 +192,12 @@ pub fn is_const_evaluatable<'tcx>( } let concrete = infcx.const_eval_resolve(param_env, uv, Some(span)); match concrete { - Err(ErrorHandled::TooGeneric) => { - Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug( - span, - format!("Missing value for constant, but no error reported?"), - ))) - } + Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error( + infcx + .tcx + .sess + .delay_span_bug(span, "Missing value for constant, but no error reported?"), + )), Err(ErrorHandled::Linted) => { let reported = infcx .tcx diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0870833cc35..8908fe230b0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -214,7 +214,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( trait_ref, item, cause, pred ); let (items, impl_def_id) = match item { - Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id), + Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { + (impl_.items, *owner_id) + } _ => return, }; let fix_span = @@ -236,7 +238,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; @@ -251,7 +253,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; @@ -303,32 +305,6 @@ impl<'tcx> WfPredicates<'tcx> { let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs) } else { - if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) { - if let Some(item) = self.item && - let hir::ItemKind::Impl(impl_) = item.kind && - let Some(trait_) = &impl_.of_trait && - let Some(def_id) = trait_.trait_def_id() && - def_id == trait_ref.def_id - { - let trait_name = tcx.item_name(def_id); - let mut err = tcx.sess.struct_span_err( - self.span, - &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"), - ); - if def_id.is_local() { - let sp = tcx.def_span(def_id).shrink_to_lo(); - err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable); - } - err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`"); - err.note("adding a non-const method body in the future would be a breaking change"); - err.emit(); - } else { - tcx.sess.span_err( - self.span, - "~const can only be applied to `#[const_trait]` traits", - ); - } - } self.nominal_obligations(trait_ref.def_id, trait_ref.substs) }; diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 3e2553c425e..424b52309d3 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -17,10 +17,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( - trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), + trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()), ), hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), ), hir::ItemKind::TraitAlias(..) => &[], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), @@ -46,7 +46,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = - impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) + impl_.items.iter().find(|i| i.id.owner_id.to_def_id() == def_id) { let assoc_item = associated_item_from_impl_item_ref(impl_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); @@ -56,7 +56,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { hir::ItemKind::Trait(.., ref trait_item_refs) => { if let Some(trait_item_ref) = - trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) + trait_item_refs.iter().find(|i| i.id.owner_id.to_def_id() == def_id) { let assoc_item = associated_item_from_trait_item_ref(trait_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); @@ -75,7 +75,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { } fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { - let def_id = trait_item_ref.id.def_id; + let owner_id = trait_item_ref.id.owner_id; let (kind, has_self) = match trait_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), @@ -85,15 +85,15 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty ty::AssocItem { name: trait_item_ref.ident.name, kind, - def_id: def_id.to_def_id(), - trait_item_def_id: Some(def_id.to_def_id()), + def_id: owner_id.to_def_id(), + trait_item_def_id: Some(owner_id.to_def_id()), container: ty::TraitContainer, fn_has_self_parameter: has_self, } } fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { - let def_id = impl_item_ref.id.def_id; + let def_id = impl_item_ref.id.owner_id; let (kind, has_self) = match impl_item_ref.kind { hir::AssocItemKind::Const => (ty::AssocKind::Const, false), hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 416c1ec510b..6436713b388 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::sym; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; @@ -236,7 +236,7 @@ fn resolve_associated_item<'tcx>( if name == sym::clone { let self_ty = trait_ref.self_ty(); - let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); + let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); match self_ty.kind() { _ if is_copy => (), ty::Generator(..) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 345911f4309..52ba0eee97c 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -399,7 +399,7 @@ fn layout_of_uncached<'tcx>( } let pointee = tcx.normalize_erasing_regions(param_env, pointee); - if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { + if pointee.is_sized(tcx, param_env) { return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); } @@ -755,8 +755,7 @@ fn layout_of_uncached<'tcx>( } else { let param_env = tcx.param_env(def.did()); let last_field = def.variant(v).fields.last().unwrap(); - let always_sized = - tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env); + let always_sized = tcx.type_of(last_field.did).is_sized(tcx, param_env); if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized } }; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d390a308153..024dcd591bd 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -109,7 +109,7 @@ where for component in components { match *component.kind() { - _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, substs) => { queue_type(self, substs.as_closure().tupled_upvars_ty()); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 196d70614e7..3eebb4ace47 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -137,10 +137,82 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { let local_did = def_id.as_local(); let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + // FIXME(consts): This is not exactly in line with the constness query. + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.is_const_default_method(def_id) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + // FIXME(consts): It's suspicious that a param-env for a foreign item + // will always have NotConst param-env, though we don't typically use + // that param-env for anything meaningful right now, so it's likely + // not an issue. + None => hir::Constness::NotConst, + }; + let unnormalized_env = ty::ParamEnv::new( tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, - tcx.constness(def_id), + constness, ); let body_id = |
