Auto merge of #120767 - matthiaskrgr:rollup-0k8ib1c, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #119592 (resolve: Unload speculatively resolved crates before freezing cstore) - #120103 (Make it so that async-fn-in-trait is compatible with a concrete future in implementation) - #120206 (hir: Make sure all `HirId`s have corresponding HIR `Node`s) - #120214 (match lowering: consistently lower bindings deepest-first) - #120688 (GVN: also turn moves into copies with projections) - #120702 (docs: also check the inline stmt during redundant link check) - #120727 (exhaustiveness: Prefer "`0..MAX` not covered" to "`_` not covered") - #120734 (Add `SubdiagnosticMessageOp` as a trait alias.) - #120739 (improve pretty printing for associated items in trait objects) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1280928a99
125 changed files with 1562 additions and 999 deletions
|
@ -1,4 +1,6 @@
|
|||
use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
|
@ -38,14 +40,8 @@ pub struct InvalidAbi {
|
|||
|
||||
pub struct InvalidAbiReason(pub &'static str);
|
||||
|
||||
impl rustc_errors::AddToDiagnostic for InvalidAbiReason {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
impl AddToDiagnostic for InvalidAbiReason {
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.note(self.0);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ struct NodeCollector<'a, 'hir> {
|
|||
bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
||||
|
||||
/// Outputs
|
||||
nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>,
|
||||
nodes: IndexVec<ItemLocalId, ParentedNode<'hir>>,
|
||||
parenting: LocalDefIdMap<ItemLocalId>,
|
||||
|
||||
/// The parent of this node
|
||||
|
@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>(
|
|||
tcx: TyCtxt<'hir>,
|
||||
item: hir::OwnerNode<'hir>,
|
||||
bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
||||
) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, LocalDefIdMap<ItemLocalId>) {
|
||||
let mut nodes = IndexVec::new();
|
||||
num_nodes: usize,
|
||||
) -> (IndexVec<ItemLocalId, ParentedNode<'hir>>, LocalDefIdMap<ItemLocalId>) {
|
||||
let zero_id = ItemLocalId::new(0);
|
||||
let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) };
|
||||
let mut nodes = IndexVec::from_elem_n(err_node, num_nodes);
|
||||
// This node's parent should never be accessed: the owner's parent is computed by the
|
||||
// hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is
|
||||
// used.
|
||||
nodes.push(Some(ParentedNode { parent: ItemLocalId::INVALID, node: item.into() }));
|
||||
nodes[zero_id] = ParentedNode { parent: ItemLocalId::INVALID, node: item.into() };
|
||||
let mut collector = NodeCollector {
|
||||
tcx,
|
||||
owner: item.def_id(),
|
||||
parent_node: ItemLocalId::new(0),
|
||||
parent_node: zero_id,
|
||||
nodes,
|
||||
bodies,
|
||||
parenting: Default::default(),
|
||||
|
@ -54,6 +57,14 @@ pub(super) fn index_hir<'hir>(
|
|||
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
|
||||
};
|
||||
|
||||
for (local_id, node) in collector.nodes.iter_enumerated() {
|
||||
if let Node::Err(span) = node.node {
|
||||
let hir_id = HirId { owner: item.def_id(), local_id };
|
||||
let msg = format!("ID {hir_id} not encountered when visiting item HIR");
|
||||
tcx.dcx().span_delayed_bug(*span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
(collector.nodes, collector.parenting)
|
||||
}
|
||||
|
||||
|
@ -88,7 +99,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node });
|
||||
self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node };
|
||||
}
|
||||
|
||||
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
|
||||
|
@ -254,6 +265,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) {
|
||||
// FIXME: walk path segment with `path_segment.hir_id` parent.
|
||||
self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment));
|
||||
intravisit::walk_path_segment(self, path_segment);
|
||||
}
|
||||
|
@ -348,4 +360,23 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
|
||||
self.visit_nested_foreign_item(id);
|
||||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) {
|
||||
match predicate {
|
||||
WherePredicate::BoundPredicate(pred) => {
|
||||
self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred));
|
||||
self.with_parent(pred.hir_id, |this| {
|
||||
intravisit::walk_where_predicate(this, predicate)
|
||||
})
|
||||
}
|
||||
_ => intravisit::walk_where_predicate(self, predicate),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_array_length(&mut self, len: &'hir ArrayLen) {
|
||||
match len {
|
||||
ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)),
|
||||
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -675,7 +675,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
} else {
|
||||
(None, None)
|
||||
};
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies);
|
||||
let num_nodes = self.item_local_id_counter.as_usize();
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
|
||||
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
|
||||
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Errors emitted by ast_passes.
|
||||
|
||||
use rustc_ast::ParamKindOrd;
|
||||
use rustc_errors::{codes::*, AddToDiagnostic, Applicability};
|
||||
use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
|
@ -372,13 +372,7 @@ pub struct EmptyLabelManySpans(pub Vec<Span>);
|
|||
|
||||
// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
|
||||
impl AddToDiagnostic for EmptyLabelManySpans {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.span_labels(self.0, "");
|
||||
}
|
||||
}
|
||||
|
@ -735,13 +729,7 @@ pub struct StableFeature {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for StableFeature {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.arg("name", self.name);
|
||||
diag.arg("since", self.since);
|
||||
diag.help(fluent::ast_passes_stable_since);
|
||||
|
|
|
@ -401,7 +401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
let hir_id = hir.parent_id(expr.hir_id);
|
||||
if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) {
|
||||
let parent = self.infcx.tcx.hir_node(hir_id);
|
||||
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
|
||||
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
|
||||
|
@ -416,10 +416,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
(None, &[][..], 0)
|
||||
};
|
||||
if let Some(def_id) = def_id
|
||||
&& let Some(node) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id))
|
||||
&& let node =
|
||||
self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id))
|
||||
&& let Some(fn_sig) = node.fn_sig()
|
||||
&& let Some(ident) = node.ident()
|
||||
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
|
||||
|
@ -448,21 +446,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let ty = place.ty(self.body, self.infcx.tcx).ty;
|
||||
if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(
|
||||
LangItem::IntoIterIntoIter,
|
||||
_,
|
||||
)) = call_expr.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
|
||||
call_expr.kind
|
||||
{
|
||||
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
|
||||
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } =
|
||||
move_spans
|
||||
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
|
||||
{
|
||||
// We already suggest cloning for these cases in `explain_captures`.
|
||||
} else {
|
||||
self.suggest_cloning(err, ty, expr, move_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pat) = finder.pat {
|
||||
*in_pattern = true;
|
||||
let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
|
||||
|
@ -1762,7 +1756,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn_decl: hir::FnDecl { inputs, .. },
|
||||
..
|
||||
}) = e.kind
|
||||
&& let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id)
|
||||
&& let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
|
||||
{
|
||||
self.suggest_arg = "this: &Self".to_string();
|
||||
if inputs.len() > 0 {
|
||||
|
@ -1828,11 +1822,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(hir::Node::ImplItem(hir::ImplItem {
|
||||
if let hir::Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(_fn_sig, body_id),
|
||||
..
|
||||
})) = self.infcx.tcx.opt_hir_node(self.mir_hir_id())
|
||||
&& let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id)
|
||||
}) = self.infcx.tcx.hir_node(self.mir_hir_id())
|
||||
&& let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id)
|
||||
{
|
||||
let mut finder = ExpressionFinder {
|
||||
capture_span: *capture_kind_span,
|
||||
|
@ -2400,8 +2394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let proper_span = proper_span.source_callsite();
|
||||
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
|
||||
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
|
||||
&& let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root)
|
||||
&& let Some(id) = node.body_id()
|
||||
&& let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id()
|
||||
&& let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
|
||||
{
|
||||
for stmt in block.stmts {
|
||||
|
|
|
@ -87,7 +87,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
|
||||
&& let [hir::PathSegment { ident, args: None, .. }] = p.segments
|
||||
&& let hir::def::Res::Local(hir_id) = p.res
|
||||
&& let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id)
|
||||
&& let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
|
||||
{
|
||||
err.span_label(pat.span, format!("binding `{ident}` declared here"));
|
||||
}
|
||||
|
|
|
@ -396,7 +396,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
let upvar_hir_id = captured_place.get_root_variable();
|
||||
|
||||
if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id)
|
||||
if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id)
|
||||
&& let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) =
|
||||
pat.kind
|
||||
{
|
||||
|
@ -688,15 +688,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
break;
|
||||
}
|
||||
f_in_trait_opt.and_then(|f_in_trait| {
|
||||
match self.infcx.tcx.opt_hir_node(f_in_trait) {
|
||||
Some(Node::TraitItem(hir::TraitItem {
|
||||
match self.infcx.tcx.hir_node(f_in_trait) {
|
||||
Node::TraitItem(hir::TraitItem {
|
||||
kind:
|
||||
hir::TraitItemKind::Fn(
|
||||
hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. },
|
||||
_,
|
||||
),
|
||||
..
|
||||
})) => {
|
||||
}) => {
|
||||
let hir::Ty { span, .. } = inputs[local.index() - 1];
|
||||
Some(span)
|
||||
}
|
||||
|
@ -759,10 +759,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
//
|
||||
// `let &b = a;` -> `let &(mut b) = a;`
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Local(hir::Local {
|
||||
&& let hir::Node::Local(hir::Local {
|
||||
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
|
||||
..
|
||||
})) = self.infcx.tcx.opt_hir_node(hir_id)
|
||||
}) = self.infcx.tcx.hir_node(hir_id)
|
||||
&& let Ok(name) =
|
||||
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
|
||||
{
|
||||
|
@ -1206,7 +1206,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id)
|
||||
&& let hir::Node::Local(local) = self.infcx.tcx.hir_node(hir_id)
|
||||
{
|
||||
let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap());
|
||||
if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait()
|
||||
|
|
|
@ -216,7 +216,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let Some(id) = placeholder.bound.kind.get_id()
|
||||
&& let Some(placeholder_id) = id.as_local()
|
||||
&& let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
|
||||
&& let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
|
||||
&& let Some(generics_impl) =
|
||||
hir.get_parent(hir.parent_id(gat_hir_id)).generics()
|
||||
{
|
||||
Some((gat_hir_id, generics_impl))
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
Level, MultiSpan, SingleLabelManySpans,
|
||||
codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee,
|
||||
IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
@ -611,13 +611,7 @@ pub(crate) struct FormatUnusedArg {
|
|||
// Allow the singular form to be a subdiagnostic of the multiple-unused
|
||||
// form of diagnostic.
|
||||
impl AddToDiagnostic for FormatUnusedArg {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
diag.arg("named", self.named);
|
||||
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
|
||||
diag.span_label(self.span, msg);
|
||||
|
|
|
@ -77,11 +77,12 @@ where
|
|||
|
||||
/// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
|
||||
/// (to optionally perform eager translation).
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage;
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F);
|
||||
}
|
||||
|
||||
pub trait SubdiagnosticMessageOp =
|
||||
Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage;
|
||||
|
||||
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
|
||||
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
|
||||
#[rustc_diagnostic_item = "DecorateLint"]
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::diagnostic::DiagnosticLocation;
|
|||
use crate::{fluent_generated as fluent, AddToDiagnostic};
|
||||
use crate::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic,
|
||||
IntoDiagnosticArg, Level,
|
||||
IntoDiagnosticArg, Level, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
@ -299,7 +299,7 @@ pub struct SingleLabelManySpans {
|
|||
pub label: &'static str,
|
||||
}
|
||||
impl AddToDiagnostic for SingleLabelManySpans {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) {
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut crate::Diagnostic, _: F) {
|
||||
diag.span_labels(self.spans, self.label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(yeet_expr)]
|
||||
// tidy-alphabetical-end
|
||||
|
@ -35,6 +36,7 @@ pub use codes::*;
|
|||
pub use diagnostic::{
|
||||
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName,
|
||||
DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic,
|
||||
SubdiagnosticMessageOp,
|
||||
};
|
||||
pub use diagnostic_builder::{
|
||||
BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic,
|
||||
|
|
|
@ -831,7 +831,7 @@ pub struct OwnerNodes<'tcx> {
|
|||
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
||||
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
|
||||
// used.
|
||||
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
|
||||
pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
|
||||
/// Content of local bodies.
|
||||
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
|
||||
}
|
||||
|
@ -839,9 +839,8 @@ pub struct OwnerNodes<'tcx> {
|
|||
impl<'tcx> OwnerNodes<'tcx> {
|
||||
pub fn node(&self) -> OwnerNode<'tcx> {
|
||||
use rustc_index::Idx;
|
||||
let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
|
||||
let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
|
||||
node
|
||||
// Indexing must ensure it is an OwnerNode.
|
||||
self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -856,9 +855,7 @@ impl fmt::Debug for OwnerNodes<'_> {
|
|||
.nodes
|
||||
.iter_enumerated()
|
||||
.map(|(id, parented_node)| {
|
||||
let parented_node = parented_node.as_ref().map(|node| node.parent);
|
||||
|
||||
debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})"))
|
||||
debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
|
@ -3347,13 +3344,15 @@ impl<'hir> OwnerNode<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
// Span by reference to pass to `Node::Err`.
|
||||
#[allow(rustc::pass_by_value)]
|
||||
pub fn span(&self) -> &'hir Span {
|
||||
match self {
|
||||
OwnerNode::Item(Item { span, .. })
|
||||
| OwnerNode::ForeignItem(ForeignItem { span, .. })
|
||||
| OwnerNode::ImplItem(ImplItem { span, .. })
|
||||
| OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
|
||||
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
|
||||
| OwnerNode::TraitItem(TraitItem { span, .. }) => span,
|
||||
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3482,17 +3481,19 @@ pub enum Node<'hir> {
|
|||
Arm(&'hir Arm<'hir>),
|
||||
Block(&'hir Block<'hir>),
|
||||
Local(&'hir Local<'hir>),
|
||||
|
||||
/// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
|
||||
/// with synthesized constructors.
|
||||
Ctor(&'hir VariantData<'hir>),
|
||||
|
||||
Lifetime(&'hir Lifetime),
|
||||
GenericParam(&'hir GenericParam<'hir>),
|
||||
|
||||
Crate(&'hir Mod<'hir>),
|
||||
|
||||
Infer(&'hir InferArg),
|
||||
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
|
||||
// FIXME: Merge into `Node::Infer`.
|
||||
ArrayLenInfer(&'hir InferArg),
|
||||
// Span by reference to minimize `Node`'s size
|
||||
#[allow(rustc::pass_by_value)]
|
||||
Err(&'hir Span),
|
||||
}
|
||||
|
||||
impl<'hir> Node<'hir> {
|
||||
|
@ -3537,7 +3538,10 @@ impl<'hir> Node<'hir> {
|
|||
| Node::Crate(..)
|
||||
| Node::Ty(..)
|
||||
| Node::TraitRef(..)
|
||||
| Node::Infer(..) => None,
|
||||
| Node::Infer(..)
|
||||
| Node::WhereBoundPredicate(..)
|
||||
| Node::ArrayLenInfer(..)
|
||||
| Node::Err(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,8 +108,8 @@ impl<'a> FnKind<'a> {
|
|||
|
||||
/// An abstract representation of the HIR `rustc_middle::hir::map::Map`.
|
||||
pub trait Map<'hir> {
|
||||
/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
|
||||
fn find(&self, hir_id: HirId) -> Option<Node<'hir>>;
|
||||
/// Retrieves the `Node` corresponding to `id`.
|
||||
fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
|
||||
fn body(&self, id: BodyId) -> &'hir Body<'hir>;
|
||||
fn item(&self, id: ItemId) -> &'hir Item<'hir>;
|
||||
fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
|
||||
|
@ -119,7 +119,7 @@ pub trait Map<'hir> {
|
|||
|
||||
// Used when no map is actually available, forcing manual implementation of nested visitors.
|
||||
impl<'hir> Map<'hir> for ! {
|
||||
fn find(&self, _: HirId) -> Option<Node<'hir>> {
|
||||
fn hir_node(&self, _: HirId) -> Node<'hir> {
|
||||
*self;
|
||||
}
|
||||
fn body(&self, _: BodyId) -> &'hir Body<'hir> {
|
||||
|
@ -669,6 +669,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
|
|||
|
||||
pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
|
||||
match len {
|
||||
// FIXME: Use `visit_infer` here.
|
||||
ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
|
||||
ArrayLen::Body(c) => visitor.visit_anon_const(c),
|
||||
}
|
||||
|
|
|
@ -33,10 +33,6 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the as
|
|||
|
||||
hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
|
||||
|
||||
hir_analysis_async_trait_impl_should_be_async =
|
||||
method `{$method_name}` should be async because the method from the trait is async
|
||||
.trait_item_label = required because the trait method is async
|
||||
|
||||
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
|
||||
.label = deref recursion limit reached
|
||||
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
|
||||
|
@ -210,6 +206,9 @@ hir_analysis_manual_implementation =
|
|||
.label = manual implementations of `{$trait_name}` are experimental
|
||||
.help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous
|
||||
.note = this method is `async` so it expects a future to be returned
|
||||
|
||||
hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
|
||||
.label = missing one of `{$missing_items_msg}` in implementation
|
||||
.note = required because of this annotation
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::potentially_plural_count;
|
||||
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
|
||||
use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
|
||||
use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
|
||||
|
@ -10,7 +10,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind};
|
|||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_infer::traits::{util, FulfillmentError};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
|
@ -74,7 +74,6 @@ fn check_method_is_structurally_compatible<'tcx>(
|
|||
compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
|
||||
compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
|
||||
compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
|
||||
compare_asyncness(tcx, impl_m, trait_m, delay)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -414,36 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn compare_asyncness<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: ty::AssocItem,
|
||||
trait_m: ty::AssocItem,
|
||||
delay: bool,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if tcx.asyncness(trait_m.def_id).is_async() {
|
||||
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
|
||||
ty::Alias(ty::Opaque, ..) => {
|
||||
// allow both `async fn foo()` and `fn foo() -> impl Future`
|
||||
}
|
||||
ty::Error(_) => {
|
||||
// We don't know if it's ok, but at least it's already an error.
|
||||
}
|
||||
_ => {
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.create_err(crate::errors::AsyncTraitImplShouldBeAsync {
|
||||
span: tcx.def_span(impl_m.def_id),
|
||||
method_name: trait_m.name,
|
||||
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
|
||||
})
|
||||
.emit_unless(delay));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Given a method def-id in an impl, compare the method signature of the impl
|
||||
/// against the trait that it's implementing. In doing so, infer the hidden types
|
||||
/// that this method's signature provides to satisfy each return-position `impl Trait`
|
||||
|
@ -695,8 +664,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
// RPITs.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
return Err(reported);
|
||||
if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig)
|
||||
{
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
|
@ -2252,3 +2226,47 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
|||
ty::AssocKind::Type => "type",
|
||||
}
|
||||
}
|
||||
|
||||
/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`,
|
||||
/// and extract a better error if so.
|
||||
fn try_report_async_mismatch<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
errors: &[FulfillmentError<'tcx>],
|
||||
trait_m: ty::AssocItem,
|
||||
impl_m: ty::AssocItem,
|
||||
impl_sig: ty::FnSig<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if !tcx.asyncness(trait_m.def_id).is_async() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) =
|
||||
*tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind()
|
||||
else {
|
||||
bug!("expected `async fn` to return an RPITIT");
|
||||
};
|
||||
|
||||
for error in errors {
|
||||
if let traits::BindingObligation(def_id, _) = *error.root_obligation.cause.code()
|
||||
&& def_id == async_future_def_id
|
||||
&& let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred()
|
||||
&& let Some(proj) = proj.no_bound_vars()
|
||||
&& infcx.can_eq(
|
||||
error.root_obligation.param_env,
|
||||
proj.term.ty().unwrap(),
|
||||
impl_sig.output(),
|
||||
)
|
||||
{
|
||||
// FIXME: We should suggest making the fn `async`, but extracting
|
||||
// the right span is a bit difficult.
|
||||
return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture {
|
||||
span: tcx.def_span(impl_m.def_id),
|
||||
method_name: trait_m.name,
|
||||
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||
return None;
|
||||
}
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
|
||||
match tcx.opt_hir_node(hir_id) {
|
||||
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
|
||||
match tcx.hir_node(hir_id) {
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
|
||||
generics.params.is_empty().not().then_some(generics.span)
|
||||
}
|
||||
_ => {
|
||||
|
@ -58,8 +58,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||
return None;
|
||||
}
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
|
||||
match tcx.opt_hir_node(hir_id) {
|
||||
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
|
||||
match tcx.hir_node(hir_id) {
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
|
||||
Some(generics.where_clause_span)
|
||||
}
|
||||
_ => {
|
||||
|
@ -80,8 +80,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||
return None;
|
||||
}
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
|
||||
match tcx.opt_hir_node(hir_id) {
|
||||
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
|
||||
match tcx.hir_node(hir_id) {
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => {
|
||||
Some(fn_sig.decl.output.span())
|
||||
}
|
||||
_ => {
|
||||
|
@ -202,7 +202,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
|
|||
let start_t = tcx.type_of(start_def_id).instantiate_identity();
|
||||
match start_t.kind() {
|
||||
ty::FnDef(..) => {
|
||||
if let Some(Node::Item(it)) = tcx.opt_hir_node(start_id) {
|
||||
if let Node::Item(it) = tcx.hir_node(start_id) {
|
||||
if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
|
|
|
@ -521,6 +521,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
|||
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
|
||||
},
|
||||
|
||||
Node::ArrayLenInfer(_) => tcx.types.usize,
|
||||
|
||||
x => {
|
||||
bug!("unexpected sort of node in type_of(): {:?}", x);
|
||||
}
|
||||
|
|
|
@ -166,17 +166,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
|||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_async_trait_impl_should_be_async)]
|
||||
pub struct AsyncTraitImplShouldBeAsync {
|
||||
#[primary_span]
|
||||
// #[label]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis_trait_item_label)]
|
||||
pub trait_item_span: Option<Span>,
|
||||
pub method_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)]
|
||||
pub struct DropImplOnWrongItem {
|
||||
|
@ -1512,6 +1501,16 @@ pub struct NotSupportedDelegation<'a> {
|
|||
pub callee_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_method_should_return_future)]
|
||||
pub struct MethodShouldReturnFuture {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub method_name: Symbol,
|
||||
#[note]
|
||||
pub trait_item_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_unused_generic_parameter)]
|
||||
pub(crate) struct UnusedGenericParameter {
|
||||
|
|
|
@ -771,8 +771,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
);
|
||||
|
||||
if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id)
|
||||
&& let Some(parent_node) = self.tcx.opt_hir_node(parent_node)
|
||||
&& let hir::Node::Expr(expr) = parent_node
|
||||
&& let hir::Node::Expr(expr) = self.tcx.hir_node(parent_node)
|
||||
{
|
||||
match &expr.kind {
|
||||
hir::ExprKind::Path(qpath) => self
|
||||
|
|
|
@ -23,7 +23,7 @@ use std::cell::Cell;
|
|||
use std::vec;
|
||||
|
||||
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String {
|
||||
to_string(&map, |s| s.print_node(map.find(hir_id).unwrap()))
|
||||
to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
|
||||
}
|
||||
|
||||
pub enum AnnNode<'a> {
|
||||
|
@ -117,6 +117,13 @@ impl<'a> State<'a> {
|
|||
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
|
||||
Node::Local(a) => self.print_local_decl(a),
|
||||
Node::Crate(..) => panic!("cannot print Crate"),
|
||||
Node::WhereBoundPredicate(pred) => {
|
||||
self.print_formal_generic_params(pred.bound_generic_params);
|
||||
self.print_type(pred.bounded_ty);
|
||||
self.print_bounds(":", pred.bounds);
|
||||
}
|
||||
Node::ArrayLenInfer(_) => self.word("_"),
|
||||
Node::Err(_) => self.word("/*ERROR*/"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1715,8 +1715,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
let ret_msg = "return a value for the case when the loop has zero elements to iterate on";
|
||||
let ret_ty_msg =
|
||||
"otherwise consider changing the return type to account for that possibility";
|
||||
if let Some(node) = tcx.opt_hir_node(item.into())
|
||||
&& let Some(body_id) = node.body_id()
|
||||
let node = tcx.hir_node(item.into());
|
||||
if let Some(body_id) = node.body_id()
|
||||
&& let Some(sig) = node.fn_sig()
|
||||
&& let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind
|
||||
&& !ty.is_never()
|
||||
|
|
|
@ -561,11 +561,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut parent;
|
||||
'outer: loop {
|
||||
// Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
|
||||
let Some(
|
||||
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. })
|
||||
let (hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. })
|
||||
| hir::Node::Block(hir::Block { expr: Some(&ref p), .. })
|
||||
| hir::Node::Expr(&ref p),
|
||||
) = self.tcx.opt_hir_node(parent_id)
|
||||
| hir::Node::Expr(&ref p)) = self.tcx.hir_node(parent_id)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
@ -578,20 +576,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut direct = false;
|
||||
loop {
|
||||
// Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
|
||||
let parent = match self.tcx.opt_hir_node(parent_id) {
|
||||
Some(hir::Node::Expr(&ref parent)) => {
|
||||
let parent = match self.tcx.hir_node(parent_id) {
|
||||
hir::Node::Expr(&ref parent) => {
|
||||
parent_id = self.tcx.hir().parent_id(parent.hir_id);
|
||||
parent
|
||||
}
|
||||
Some(hir::Node::Stmt(hir::Stmt {
|
||||
hir::Node::Stmt(hir::Stmt {
|
||||
hir_id,
|
||||
kind: hir::StmtKind::Semi(&ref parent) | hir::StmtKind::Expr(&ref parent),
|
||||
..
|
||||
})) => {
|
||||
}) => {
|
||||
parent_id = self.tcx.hir().parent_id(*hir_id);
|
||||
parent
|
||||
}
|
||||
Some(hir::Node::Block(_)) => {
|
||||
hir::Node::Block(_) => {
|
||||
parent_id = self.tcx.hir().parent_id(parent_id);
|
||||
parent
|
||||
}
|
||||
|
@ -680,17 +678,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
error: Option<TypeError<'tcx>>,
|
||||
) {
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
match (self.tcx.opt_hir_node(parent), error) {
|
||||
(Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
|
||||
match (self.tcx.hir_node(parent), error) {
|
||||
(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. }), _)
|
||||
if init.hir_id == expr.hir_id =>
|
||||
{
|
||||
// Point at `let` assignment type.
|
||||
err.span_label(ty.span, "expected due to this");
|
||||
}
|
||||
(
|
||||
Some(hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Assign(lhs, rhs, _), ..
|
||||
})),
|
||||
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }),
|
||||
Some(TypeError::Sorts(ExpectedFound { expected, .. })),
|
||||
) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
|
||||
// We ignore closures explicitly because we already point at them elsewhere.
|
||||
|
@ -725,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None,
|
||||
hir::Path { res: hir::def::Res::Local(hir_id), .. },
|
||||
)) => {
|
||||
if let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) {
|
||||
if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) {
|
||||
primary_span = pat.span;
|
||||
secondary_span = pat.span;
|
||||
match self.tcx.hir().find_parent(pat.hir_id) {
|
||||
|
@ -774,9 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
(
|
||||
Some(hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Binary(_, lhs, rhs), ..
|
||||
})),
|
||||
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }),
|
||||
Some(TypeError::Sorts(ExpectedFound { expected, .. })),
|
||||
) if rhs.hir_id == expr.hir_id
|
||||
&& self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) =>
|
||||
|
@ -797,8 +791,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) =
|
||||
self.tcx.opt_hir_node(parent)
|
||||
let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
|
||||
self.tcx.hir_node(parent)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
@ -1022,13 +1016,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
|
||||
)) = expr.kind
|
||||
{
|
||||
let bind = self.tcx.opt_hir_node(*bind_hir_id);
|
||||
let parent = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*bind_hir_id));
|
||||
if let Some(hir::Node::Pat(hir::Pat {
|
||||
kind: hir::PatKind::Binding(_, _hir_id, _, _),
|
||||
..
|
||||
})) = bind
|
||||
&& let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent
|
||||
let bind = self.tcx.hir_node(*bind_hir_id);
|
||||
let parent = self.tcx.hir_node(self.tcx.hir().parent_id(*bind_hir_id));
|
||||
if let hir::Node::Pat(hir::Pat {
|
||||
kind: hir::PatKind::Binding(_, _hir_id, _, _), ..
|
||||
}) = bind
|
||||
&& let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::borrow::Cow;
|
|||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg,
|
||||
MultiSpan, SubdiagnosticMessage,
|
||||
MultiSpan, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
|
@ -195,10 +195,7 @@ pub struct TypeMismatchFruTypo {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for TypeMismatchFruTypo {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
|
||||
|
||||
// Only explain that `a ..b` is a range if it's split up
|
||||
|
@ -373,10 +370,7 @@ pub struct RemoveSemiForCoerce {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for RemoveSemiForCoerce {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let mut multispan: MultiSpan = self.semi.into();
|
||||
multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
|
||||
multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret);
|
||||
|
@ -547,14 +541,8 @@ pub enum CastUnknownPointerSub {
|
|||
From(Span),
|
||||
}
|
||||
|
||||
impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(
|
||||
&mut Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage,
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
{
|
||||
impl AddToDiagnostic for CastUnknownPointerSub {
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
match self {
|
||||
CastUnknownPointerSub::To(span) => {
|
||||
let msg = f(diag, crate::fluent_generated::hir_typeck_label_to);
|
||||
|
|
|
@ -1017,7 +1017,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
then: impl FnOnce(&hir::Expr<'_>),
|
||||
) {
|
||||
let mut parent = self.tcx.hir().parent_id(original_expr_id);
|
||||
while let Some(node) = self.tcx.opt_hir_node(parent) {
|
||||
loop {
|
||||
let node = self.tcx.hir_node(parent);
|
||||
match node {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind:
|
||||
|
@ -1471,8 +1472,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
|
||||
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
|
||||
&& let Some(span) = self.tcx.hir().opt_span(hir_id)
|
||||
{
|
||||
let span = self.tcx.hir().span(hir_id);
|
||||
match self.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
|
||||
Some(mut err) => {
|
||||
err.span_suggestion(
|
||||
|
|
|
@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let node = self
|
||||
.tcx
|
||||
.opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id))
|
||||
.and_then(|hir_id| self.tcx.opt_hir_node(hir_id));
|
||||
.map(|hir_id| self.tcx.hir_node(hir_id));
|
||||
match node {
|
||||
Some(hir::Node::Item(item)) => call_finder.visit_item(item),
|
||||
Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item),
|
||||
|
|
|
@ -682,8 +682,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// is and we were expecting a Box, ergo Pin<Box<expected>>, we
|
||||
// can suggest Box::pin.
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) =
|
||||
self.tcx.opt_hir_node(parent)
|
||||
let Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. }) =
|
||||
self.tcx.hir_node(parent)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
@ -908,9 +908,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let ty::Param(expected_ty_as_param) = expected.kind() else { return };
|
||||
|
||||
let fn_node = self.tcx.opt_hir_node(fn_id);
|
||||
let fn_node = self.tcx.hir_node(fn_id);
|
||||
|
||||
let Some(hir::Node::Item(hir::Item {
|
||||
let hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::Fn(
|
||||
hir::FnSig {
|
||||
|
@ -921,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_body_id,
|
||||
),
|
||||
..
|
||||
})) = fn_node
|
||||
}) = fn_node
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
@ -1053,9 +1053,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
let ty = self.normalize(expr.span, ty);
|
||||
if self.can_coerce(found, ty) {
|
||||
if let Some(node) = self.tcx.opt_hir_node(fn_id)
|
||||
&& let Some(owner_node) = node.as_owner()
|
||||
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
|
||||
if let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner()
|
||||
&& let Some(span) = expr.span.find_ancestor_inside(*owner_node.span())
|
||||
{
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to return this value",
|
||||
|
@ -1684,15 +1683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
None,
|
||||
hir::Path { segments: [_], res: crate::Res::Local(binding), .. },
|
||||
)) => {
|
||||
let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding)
|
||||
else {
|
||||
return expr;
|
||||
};
|
||||
let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else {
|
||||
let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) else {
|
||||
return expr;
|
||||
};
|
||||
|
||||
match parent {
|
||||
match self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) {
|
||||
// foo.clone()
|
||||
hir::Node::Local(hir::Local { init: Some(init), .. }) => {
|
||||
self.note_type_is_not_clone_inner_expr(init)
|
||||
|
@ -1703,8 +1698,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
kind: hir::PatKind::Tuple(pats, ..),
|
||||
..
|
||||
}) => {
|
||||
let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) =
|
||||
self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id))
|
||||
let hir::Node::Local(hir::Local { init: Some(init), .. }) =
|
||||
self.tcx.hir_node(self.tcx.hir().parent_id(*pat_hir_id))
|
||||
else {
|
||||
return expr;
|
||||
};
|
||||
|
@ -1736,10 +1731,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
call_expr_kind
|
||||
&& let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } =
|
||||
call_expr_path
|
||||
&& let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) =
|
||||
self.tcx.opt_hir_node(*binding)
|
||||
&& let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id))
|
||||
&& let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure
|
||||
&& let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding)
|
||||
&& let hir::Node::Local(hir::Local { init: Some(init), .. }) =
|
||||
self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id))
|
||||
&& let Expr {
|
||||
kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }),
|
||||
..
|
||||
|
@ -1979,20 +1973,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Unroll desugaring, to make sure this works for `for` loops etc.
|
||||
loop {
|
||||
parent = self.tcx.hir().parent_id(id);
|
||||
if let Some(parent_span) = self.tcx.hir().opt_span(parent) {
|
||||
let parent_span = self.tcx.hir().span(parent);
|
||||
if parent_span.find_ancestor_inside(expr.span).is_some() {
|
||||
// The parent node is part of the same span, so is the result of the
|
||||
// same expansion/desugaring and not the 'real' parent node.
|
||||
id = parent;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some(hir::Node::Block(&hir::Block {
|
||||
span: block_span, expr: Some(e), ..
|
||||
})) = self.tcx.opt_hir_node(parent)
|
||||
if let hir::Node::Block(&hir::Block { span: block_span, expr: Some(e), .. }) =
|
||||
self.tcx.hir_node(parent)
|
||||
{
|
||||
if e.hir_id == id {
|
||||
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
|
||||
|
@ -2220,30 +2212,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let local_parent = self.tcx.hir().parent_id(local_id);
|
||||
let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) =
|
||||
self.tcx.opt_hir_node(local_parent)
|
||||
let Node::Param(hir::Param { hir_id: param_hir_id, .. }) = self.tcx.hir_node(local_parent)
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let param_parent = self.tcx.hir().parent_id(*param_hir_id);
|
||||
let Some(Node::Expr(hir::Expr {
|
||||
let Node::Expr(hir::Expr {
|
||||
hir_id: expr_hir_id,
|
||||
kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
|
||||
..
|
||||
})) = self.tcx.opt_hir_node(param_parent)
|
||||
}) = self.tcx.hir_node(param_parent)
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let expr_parent = self.tcx.hir().parent_id(*expr_hir_id);
|
||||
let hir = self.tcx.opt_hir_node(expr_parent);
|
||||
let hir = self.tcx.hir_node(expr_parent);
|
||||
let closure_params_len = closure_fn_decl.inputs.len();
|
||||
let (
|
||||
Some(Node::Expr(hir::Expr {
|
||||
Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::MethodCall(method_path, receiver, ..),
|
||||
..
|
||||
})),
|
||||
}),
|
||||
1,
|
||||
) = (hir, closure_params_len)
|
||||
else {
|
||||
|
@ -2674,10 +2665,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
if let hir::ExprKind::If(..) = expr.kind {
|
||||
let parent_id = self.tcx.hir().parent_id(expr.hir_id);
|
||||
if let Some(Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::If(_, _, Some(else_expr)),
|
||||
..
|
||||
})) = self.tcx.opt_hir_node(parent_id)
|
||||
if let Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::If(_, _, Some(else_expr)), ..
|
||||
}) = self.tcx.hir_node(parent_id)
|
||||
{
|
||||
return else_expr.hir_id == expr.hir_id;
|
||||
}
|
||||
|
@ -3067,7 +3057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) {
|
||||
if let hir::Node::ExprField(_) = self.tcx.hir_node(parent) {
|
||||
// Ignore `Foo { field: a..Default::default() }`
|
||||
return;
|
||||
}
|
||||
|
@ -3146,7 +3136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let hir::def::Res::Local(hir_id) = path.res else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else {
|
||||
let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
|
||||
|
|
|
@ -230,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
|
||||
&& let hir::def::Res::Local(hir_id) = path.res
|
||||
&& let Some(hir::Node::Pat(b)) = self.tcx.opt_hir_node(hir_id)
|
||||
&& let hir::Node::Pat(b) = self.tcx.hir_node(hir_id)
|
||||
&& let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
|
||||
&& let Some(node) = self.tcx.hir().find_parent(p.hir_id)
|
||||
&& let Some(decl) = node.fn_decl()
|
||||
|
@ -2017,7 +2017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
visitor.visit_body(body);
|
||||
|
||||
let parent = self.tcx.hir().parent_id(seg1.hir_id);
|
||||
if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent)
|
||||
if let Node::Expr(call_expr) = self.tcx.hir_node(parent)
|
||||
&& let Some(expr) = visitor.result
|
||||
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
|
||||
{
|
||||
|
@ -3251,7 +3251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let parent = self.tcx.hir().parent_id(expr.hir_id);
|
||||
if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent)
|
||||
if let Node::Expr(call_expr) = self.tcx.hir_node(parent)
|
||||
&& let hir::ExprKind::MethodCall(
|
||||
hir::PathSegment { ident: method_name, .. },
|
||||
self_expr,
|
||||
|
|
|
@ -73,9 +73,7 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>(
|
|||
debug!("start resolving rvalue scopes, def_id={def_id:?}");
|
||||
debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates);
|
||||
for (&hir_id, candidate) in &scope_tree.rvalue_candidates {
|
||||
let Some(Node::Expr(expr)) = tcx.opt_hir_node(hir_id) else {
|
||||
bug!("hir node does not exist")
|
||||
};
|
||||
let Node::Expr(expr) = tcx.hir_node(hir_id) else { bug!("hir node does not exist") };
|
||||
record_rvalue_scope(&mut rvalue_scopes, expr, candidate);
|
||||
}
|
||||
rvalue_scopes
|
||||
|
|
|
@ -972,9 +972,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
|
||||
if s.starts_with('$') {
|
||||
// Looks like a macro fragment. Try to find the real block.
|
||||
if let Some(hir::Node::Expr(&hir::Expr {
|
||||
if let hir::Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::Block(block, ..), ..
|
||||
})) = self.tcx.opt_hir_node(body_id.hir_id) {
|
||||
}) = self.tcx.hir_node(body_id.hir_id) {
|
||||
// If the body is a block (with `{..}`), we use the span of that block.
|
||||
// E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`.
|
||||
// Since we know it's a block, we know we can insert the `let _ = ..` without
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use hir::GenericParamKind;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage,
|
||||
DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
|
||||
DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::FnRetTy;
|
||||
|
@ -225,10 +225,7 @@ pub enum RegionOriginNote<'a> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for RegionOriginNote<'_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let mut label_or_note = |span, msg: DiagnosticMessage| {
|
||||
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
|
||||
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
|
||||
|
@ -289,10 +286,7 @@ pub enum LifetimeMismatchLabels {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for LifetimeMismatchLabels {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
|
||||
diag.span_label(param_span, fluent::infer_declared_different);
|
||||
|
@ -336,10 +330,7 @@ pub struct AddLifetimeParamsSuggestion<'a> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let mut mk_suggestion = || {
|
||||
let (
|
||||
hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. },
|
||||
|
@ -437,10 +428,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
|
||||
fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(mut self, diag: &mut Diagnostic, _: F) {
|
||||
self.unmet_requirements
|
||||
.push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
|
||||
diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
|
||||
|
@ -755,10 +743,7 @@ pub struct ConsiderBorrowingParamHelp {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for ConsiderBorrowingParamHelp {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
let mut type_param_span: MultiSpan = self.spans.clone().into();
|
||||
for &span in &self.spans {
|
||||
// Seems like we can't call f() here as Into<DiagnosticMessage> is required
|
||||
|
@ -799,10 +784,7 @@ pub struct DynTraitConstraintSuggestion {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for DynTraitConstraintSuggestion {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
let mut multi_span: MultiSpan = vec![self.span].into();
|
||||
multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
|
||||
multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
|
||||
|
@ -845,10 +827,7 @@ pub struct ReqIntroducedLocations {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for ReqIntroducedLocations {
|
||||
fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(mut self, diag: &mut Diagnostic, f: F) {
|
||||
for sp in self.spans {
|
||||
self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
|
||||
}
|
||||
|
@ -867,10 +846,7 @@ pub struct MoreTargeted {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for MoreTargeted {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _f: F) {
|
||||
diag.code(E0772);
|
||||
diag.primary_message(fluent::infer_more_targeted);
|
||||
diag.arg("ident", self.ident);
|
||||
|
@ -1289,10 +1265,7 @@ pub struct SuggestTuplePatternMany {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for SuggestTuplePatternMany {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
diag.arg("path", self.path);
|
||||
let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
|
||||
diag.multipart_suggestions(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::fluent_generated as fluent;
|
||||
use crate::infer::error_reporting::nice_region_error::find_anon_type;
|
||||
use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
|
||||
use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessageOp};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::{symbol::kw, Span};
|
||||
|
||||
|
@ -160,10 +160,7 @@ impl RegionExplanation<'_> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for RegionExplanation<'_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) {
|
||||
diag.arg("pref_kind", self.prefix);
|
||||
diag.arg("suff_kind", self.suffix);
|
||||
diag.arg("desc_kind", self.desc.kind);
|
||||
|
|
|
@ -2182,8 +2182,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
if let Some(tykind) = tykind
|
||||
&& let hir::TyKind::Array(_, length) = tykind
|
||||
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
|
||||
&& let Some(span) = self.tcx.hir().opt_span(*hir_id)
|
||||
{
|
||||
let span = self.tcx.hir().span(*hir_id);
|
||||
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -687,7 +687,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi
|
|||
let res = hir_id == scope;
|
||||
trace!(
|
||||
"may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
|
||||
tcx.opt_hir_node(hir_id),
|
||||
tcx.hir_node(hir_id),
|
||||
tcx.hir_node(opaque_hir_id),
|
||||
res
|
||||
);
|
||||
|
|
|
@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxIndexSet;
|
|||
use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Map;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
@ -62,7 +61,7 @@ pub fn report_object_safety_error<'tcx>(
|
|||
err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
|
||||
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id)
|
||||
&& let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
|
||||
&& let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
|
||||
{
|
||||
let mut hir_id = hir_id;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
|
||||
use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
@ -24,10 +24,7 @@ pub enum OverruledAttributeSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for OverruledAttributeSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
OverruledAttributeSub::DefaultSource { id } => {
|
||||
diag.note(fluent::lint_default_source);
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::errors::RequestedLevel;
|
|||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder,
|
||||
DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
|
||||
DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessageOp, SuggestionStyle,
|
||||
};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
|
@ -268,10 +268,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
// Access to associates types should use `<T as Bound>::Assoc`, which does not need a
|
||||
// bound. Let's see if this type does that.
|
||||
|
||||
|
@ -323,10 +320,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_suggestion,
|
||||
self.suggestions,
|
||||
|
@ -443,10 +437,7 @@ pub struct BuiltinUnpermittedTypeInitSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let mut err = self.err;
|
||||
loop {
|
||||
if let Some(span) = err.span {
|
||||
|
@ -497,10 +488,7 @@ pub struct BuiltinClashingExternSub<'a> {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for BuiltinClashingExternSub<'_> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let mut expected_str = DiagnosticStyledString::new();
|
||||
expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
|
||||
let mut found_str = DiagnosticStyledString::new();
|
||||
|
@ -766,10 +754,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
for (c, span) in self.spans {
|
||||
diag.span_label(span, format!("{c:?}"));
|
||||
}
|
||||
|
@ -783,10 +768,7 @@ pub enum HiddenUnicodeCodepointsDiagSub {
|
|||
|
||||
// Used because of multiple multipart_suggestion and note
|
||||
impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
|
||||
diag.multipart_suggestion_with_style(
|
||||
|
@ -934,10 +916,7 @@ pub struct NonBindingLetSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for NonBindingLetSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
|
||||
|
||||
if can_suggest_binding {
|
||||
|
@ -1217,10 +1196,7 @@ pub enum NonSnakeCaseDiagSub {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for NonSnakeCaseDiagSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
NonSnakeCaseDiagSub::Label { span } => {
|
||||
diag.span_label(span, fluent::lint_label);
|
||||
|
@ -1413,10 +1389,7 @@ pub enum OverflowingBinHexSign {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for OverflowingBinHexSign {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
OverflowingBinHexSign::Positive => {
|
||||
diag.note(fluent::lint_positive_note);
|
||||
|
|
|
@ -89,10 +89,7 @@ impl SubdiagnosticDeriveBuilder {
|
|||
gen impl rustc_errors::AddToDiagnostic for @Self {
|
||||
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
|
||||
where
|
||||
__F: core::ops::Fn(
|
||||
&mut rustc_errors::Diagnostic,
|
||||
rustc_errors::SubdiagnosticMessage
|
||||
) -> rustc_errors::SubdiagnosticMessage,
|
||||
__F: rustc_errors::SubdiagnosticMessageOp,
|
||||
{
|
||||
#implementation
|
||||
}
|
||||
|
|
|
@ -534,7 +534,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
) -> Option<CrateNum> {
|
||||
self.used_extern_options.insert(name);
|
||||
match self.maybe_resolve_crate(name, dep_kind, None) {
|
||||
Ok(cnum) => Some(cnum),
|
||||
Ok(cnum) => {
|
||||
self.cstore.set_used_recursively(cnum);
|
||||
Some(cnum)
|
||||
}
|
||||
Err(err) => {
|
||||
let missing_core =
|
||||
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
|
||||
|
@ -1067,6 +1070,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
|
||||
self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
|
||||
}
|
||||
|
||||
pub fn unload_unused_crates(&mut self) {
|
||||
for opt_cdata in &mut self.cstore.metas {
|
||||
if let Some(cdata) = opt_cdata
|
||||
&& !cdata.used()
|
||||
{
|
||||
*opt_cdata = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
|
||||
|
|
|
@ -106,6 +106,8 @@ pub(crate) struct CrateMetadata {
|
|||
private_dep: bool,
|
||||
/// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
|
||||
host_hash: Option<Svh>,
|
||||
/// The crate was used non-speculatively.
|
||||
used: bool,
|
||||
|
||||
/// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
|
||||
/// and `ExpnId`).
|
||||
|
@ -1811,6 +1813,7 @@ impl CrateMetadata {
|
|||
source: Lrc::new(source),
|
||||
private_dep,
|
||||
host_hash,
|
||||
used: false,
|
||||
extern_crate: None,
|
||||
hygiene_context: Default::default(),
|
||||
def_key_cache: Default::default(),
|
||||
|
@ -1860,6 +1863,10 @@ impl CrateMetadata {
|
|||
self.private_dep &= private_dep;
|
||||
}
|
||||
|
||||
pub(crate) fn used(&self) -> bool {
|
||||
self.used
|
||||
}
|
||||
|
||||
pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
|
||||
self.root.required_panic_strategy
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, Symbol};
|
|||
use rustc_span::Span;
|
||||
|
||||
use std::any::Any;
|
||||
use std::mem;
|
||||
|
||||
use super::{Decodable, DecodeContext, DecodeIterator};
|
||||
|
||||
|
@ -576,12 +577,24 @@ impl CStore {
|
|||
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
|
||||
}
|
||||
|
||||
pub fn set_used_recursively(&mut self, cnum: CrateNum) {
|
||||
let cmeta = self.get_crate_data_mut(cnum);
|
||||
if !cmeta.used {
|
||||
cmeta.used = true;
|
||||
let dependencies = mem::take(&mut cmeta.dependencies);
|
||||
for &dep_cnum in &dependencies {
|
||||
self.set_used_recursively(dep_cnum);
|
||||
}
|
||||
self.get_crate_data_mut(cnum).dependencies = dependencies;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) {
|
||||
let cmeta = self.get_crate_data_mut(cnum);
|
||||
if cmeta.update_extern_crate(extern_crate) {
|
||||
// Propagate the extern crate info to dependencies if it was updated.
|
||||
let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate };
|
||||
let dependencies = std::mem::take(&mut cmeta.dependencies);
|
||||
let dependencies = mem::take(&mut cmeta.dependencies);
|
||||
for &dep_cnum in &dependencies {
|
||||
self.update_extern_crate(dep_cnum, extern_crate);
|
||||
}
|
||||
|
|
|
@ -1388,13 +1388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
if should_encode_fn_sig(def_kind) {
|
||||
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
|
||||
}
|
||||
// FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]`
|
||||
// do not have corresponding HIR nodes, so some queries usually making sense for
|
||||
// anonymous constants will not work on them and panic. It's not clear whether it
|
||||
// can cause any observable issues or not.
|
||||
let anon_const_without_hir = def_kind == DefKind::AnonConst
|
||||
&& tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none();
|
||||
if should_encode_generics(def_kind) && !anon_const_without_hir {
|
||||
if should_encode_generics(def_kind) {
|
||||
let g = tcx.generics_of(def_id);
|
||||
record!(self.tables.generics_of[def_id] <- g);
|
||||
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
|
||||
|
@ -1408,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir {
|
||||
if should_encode_type(tcx, local_id, def_kind) {
|
||||
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
|
||||
}
|
||||
if should_encode_constness(def_kind) {
|
||||
|
|
|
@ -157,23 +157,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.hir_owner_nodes(owner_id).node()
|
||||
}
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
|
||||
pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> {
|
||||
let owner = self.hir_owner_nodes(id.owner);
|
||||
let node = owner.nodes[id.local_id].as_ref()?;
|
||||
Some(node.node)
|
||||
}
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
|
||||
#[inline]
|
||||
pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option<Node<'tcx>> {
|
||||
self.opt_hir_node(self.opt_local_def_id_to_hir_id(id)?)
|
||||
Some(self.hir_node(self.opt_local_def_id_to_hir_id(id)?))
|
||||
}
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found.
|
||||
#[track_caller]
|
||||
/// Retrieves the `hir::Node` corresponding to `id`.
|
||||
pub fn hir_node(self, id: HirId) -> Node<'tcx> {
|
||||
self.opt_hir_node(id).unwrap_or_else(|| bug!("couldn't find HIR node for hir id {id:?}"))
|
||||
self.hir_owner_nodes(id.owner).nodes[id.local_id].node
|
||||
}
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found.
|
||||
|
@ -230,10 +222,13 @@ impl<'hir> Map<'hir> {
|
|||
/// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
|
||||
pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
|
||||
if id.local_id == ItemLocalId::from_u32(0) {
|
||||
// FIXME: This function never returns `None` right now, and the parent chain end is
|
||||
// determined by checking for `parent(id) == id`. This function should return `None`
|
||||
// for the crate root instead.
|
||||
Some(self.tcx.hir_owner_parent(id.owner))
|
||||
} else {
|
||||
let owner = self.tcx.hir_owner_nodes(id.owner);
|
||||
let node = owner.nodes[id.local_id].as_ref()?;
|
||||
let node = &owner.nodes[id.local_id];
|
||||
let hir_id = HirId { owner: id.owner, local_id: node.parent };
|
||||
// HIR indexing should have checked that.
|
||||
debug_assert_ne!(id.local_id, node.parent);
|
||||
|
@ -252,11 +247,12 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
|
||||
self.tcx.opt_hir_node(self.opt_parent_id(hir_id)?)
|
||||
Some(self.tcx.hir_node(self.opt_parent_id(hir_id)?))
|
||||
}
|
||||
|
||||
pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> {
|
||||
id.as_local().and_then(|id| self.tcx.opt_hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))
|
||||
id.as_local()
|
||||
.and_then(|id| Some(self.tcx.hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?)))
|
||||
}
|
||||
|
||||
pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
|
||||
|
@ -285,20 +281,12 @@ impl<'hir> Map<'hir> {
|
|||
|
||||
#[track_caller]
|
||||
pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
|
||||
if let Some(node) = self.tcx.opt_hir_node(hir_id) {
|
||||
node.fn_decl()
|
||||
} else {
|
||||
bug!("no node for hir_id `{}`", hir_id)
|
||||
}
|
||||
self.tcx.hir_node(hir_id).fn_decl()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
|
||||
if let Some(node) = self.tcx.opt_hir_node(hir_id) {
|
||||
node.fn_sig()
|
||||
} else {
|
||||
bug!("no node for hir_id `{}`", hir_id)
|
||||
}
|
||||
self.tcx.hir_node(hir_id).fn_sig()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
@ -317,10 +305,7 @@ impl<'hir> Map<'hir> {
|
|||
/// item (possibly associated), a closure, or a `hir::AnonConst`.
|
||||
pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
|
||||
let parent = self.parent_id(hir_id);
|
||||
assert!(
|
||||
self.tcx.opt_hir_node(parent).is_some_and(|n| is_body_owner(n, hir_id)),
|
||||
"{hir_id:?}"
|
||||
);
|
||||
assert!(is_body_owner(self.tcx.hir_node(parent), hir_id), "{hir_id:?}");
|
||||
parent
|
||||
}
|
||||
|
||||
|
@ -572,7 +557,7 @@ impl<'hir> Map<'hir> {
|
|||
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
|
||||
#[inline]
|
||||
pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> {
|
||||
self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.tcx.opt_hir_node(id)?)))
|
||||
self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id)))
|
||||
}
|
||||
|
||||
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
||||
|
@ -624,7 +609,7 @@ impl<'hir> Map<'hir> {
|
|||
pub fn get_return_block(self, id: HirId) -> Option<HirId> {
|
||||
let mut iter = self.parent_iter(id).peekable();
|
||||
let mut ignore_tail = false;
|
||||
if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.tcx.opt_hir_node(id) {
|
||||
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) {
|
||||
// When dealing with `return` statements, we don't care about climbing only tail
|
||||
// expressions.
|
||||
ignore_tail = true;
|
||||
|
@ -777,8 +762,8 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
|
||||
match self.tcx.opt_hir_node(id) {
|
||||
Some(Node::Variant(variant)) => variant,
|
||||
match self.tcx.hir_node(id) {
|
||||
Node::Variant(variant) => variant,
|
||||
_ => bug!("expected variant, found {}", self.node_to_string(id)),
|
||||
}
|
||||
}
|
||||
|
@ -796,18 +781,18 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
|
||||
match self.tcx.opt_hir_node(id) {
|
||||
Some(Node::Expr(expr)) => expr,
|
||||
match self.tcx.hir_node(id) {
|
||||
Node::Expr(expr) => expr,
|
||||
_ => bug!("expected expr, found {}", self.node_to_string(id)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn opt_ident(self, id: HirId) -> Option<Ident> {
|
||||
match self.tcx.opt_hir_node(id)? {
|
||||
match self.tcx.hir_node(id) {
|
||||
Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
|
||||
// A `Ctor` doesn't have an identifier itself, but its parent
|
||||
// struct/variant does. Compare with `hir::Map::opt_span`.
|
||||
// struct/variant does. Compare with `hir::Map::span`.
|
||||
Node::Ctor(..) => match self.find_parent(id)? {
|
||||
Node::Item(item) => Some(item.ident),
|
||||
Node::Variant(variant) => Some(variant.ident),
|
||||
|
@ -845,11 +830,6 @@ impl<'hir> Map<'hir> {
|
|||
/// Gets the span of the definition of the specified HIR node.
|
||||
/// This is used by `tcx.def_span`.
|
||||
pub fn span(self, hir_id: HirId) -> Span {
|
||||
self.opt_span(hir_id)
|
||||
.unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id))
|
||||
}
|
||||
|
||||
pub fn opt_span(self, hir_id: HirId) -> Option<Span> {
|
||||
fn until_within(outer: Span, end: Span) -> Span {
|
||||
if let Some(end) = end.find_ancestor_inside(outer) {
|
||||
outer.with_hi(end.hi())
|
||||
|
@ -873,7 +853,7 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
let span = match self.tcx.opt_hir_node(hir_id)? {
|
||||
let span = match self.tcx.hir_node(hir_id) {
|
||||
// Function-like.
|
||||
Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. })
|
||||
| Node::TraitItem(TraitItem {
|
||||
|
@ -945,7 +925,7 @@ impl<'hir> Map<'hir> {
|
|||
ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
|
||||
_ => named_span(item.span, item.ident, None),
|
||||
},
|
||||
Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)),
|
||||
Node::Ctor(_) => return self.span(self.parent_id(hir_id)),
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
|
||||
span,
|
||||
|
@ -957,7 +937,7 @@ impl<'hir> Map<'hir> {
|
|||
_ => self.span_with_body(hir_id),
|
||||
};
|
||||
debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt());
|
||||
Some(span)
|
||||
span
|
||||
}
|
||||
|
||||
/// Like `hir.span()`, but includes the body of items
|
||||
|
@ -994,6 +974,9 @@ impl<'hir> Map<'hir> {
|
|||
Node::Infer(i) => i.span,
|
||||
Node::Local(local) => local.span,
|
||||
Node::Crate(item) => item.spans.inner_span,
|
||||
Node::WhereBoundPredicate(pred) => pred.span,
|
||||
Node::ArrayLenInfer(inf) => inf.span,
|
||||
Node::Err(span) => *span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1057,8 +1040,8 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> intravisit::Map<'hir> for Map<'hir> {
|
||||
fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
|
||||
self.tcx.opt_hir_node(hir_id)
|
||||
fn hir_node(&self, hir_id: HirId) -> Node<'hir> {
|
||||
self.tcx.hir_node(hir_id)
|
||||
}
|
||||
|
||||
fn body(&self, id: BodyId) -> &'hir Body<'hir> {
|
||||
|
@ -1175,8 +1158,8 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
|
||||
let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
|
||||
|
||||
match map.tcx.opt_hir_node(id) {
|
||||
Some(Node::Item(item)) => {
|
||||
match map.tcx.hir_node(id) {
|
||||
Node::Item(item) => {
|
||||
let item_str = match item.kind {
|
||||
ItemKind::ExternCrate(..) => "extern crate",
|
||||
ItemKind::Use(..) => "use",
|
||||
|
@ -1204,10 +1187,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
};
|
||||
format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
|
||||
}
|
||||
Some(Node::ForeignItem(item)) => {
|
||||
Node::ForeignItem(item) => {
|
||||
format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
|
||||
}
|
||||
Some(Node::ImplItem(ii)) => {
|
||||
Node::ImplItem(ii) => {
|
||||
let kind = match ii.kind {
|
||||
ImplItemKind::Const(..) => "assoc const",
|
||||
ImplItemKind::Fn(..) => "method",
|
||||
|
@ -1215,7 +1198,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
};
|
||||
format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
|
||||
}
|
||||
Some(Node::TraitItem(ti)) => {
|
||||
Node::TraitItem(ti) => {
|
||||
let kind = match ti.kind {
|
||||
TraitItemKind::Const(..) => "assoc constant",
|
||||
TraitItemKind::Fn(..) => "trait method",
|
||||
|
@ -1224,38 +1207,40 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
|
||||
format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
|
||||
}
|
||||
Some(Node::Variant(variant)) => {
|
||||
Node::Variant(variant) => {
|
||||
format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
|
||||
}
|
||||
Some(Node::Field(field)) => {
|
||||
Node::Field(field) => {
|
||||
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
|
||||
}
|
||||
Some(Node::AnonConst(_)) => node_str("const"),
|
||||
Some(Node::ConstBlock(_)) => node_str("const"),
|
||||
Some(Node::Expr(_)) => node_str("expr"),
|
||||
Some(Node::ExprField(_)) => node_str("expr field"),
|
||||
Some(Node::Stmt(_)) => node_str("stmt"),
|
||||
Some(Node::PathSegment(_)) => node_str("path segment"),
|
||||
Some(Node::Ty(_)) => node_str("type"),
|
||||
Some(Node::TypeBinding(_)) => node_str("type binding"),
|
||||
Some(Node::TraitRef(_)) => node_str("trait ref"),
|
||||
Some(Node::Pat(_)) => node_str("pat"),
|
||||
Some(Node::PatField(_)) => node_str("pattern field"),
|
||||
Some(Node::Param(_)) => node_str("param"),
|
||||
Some(Node::Arm(_)) => node_str("arm"),
|
||||
Some(Node::Block(_)) => node_str("block"),
|
||||
Some(Node::Infer(_)) => node_str("infer"),
|
||||
Some(Node::Local(_)) => node_str("local"),
|
||||
Some(Node::Ctor(ctor)) => format!(
|
||||
Node::AnonConst(_) => node_str("const"),
|
||||
Node::ConstBlock(_) => node_str("const"),
|
||||
Node::Expr(_) => node_str("expr"),
|
||||
Node::ExprField(_) => node_str("expr field"),
|
||||
Node::Stmt(_) => node_str("stmt"),
|
||||
Node::PathSegment(_) => node_str("path segment"),
|
||||
Node::Ty(_) => node_str("type"),
|
||||
Node::TypeBinding(_) => node_str("type binding"),
|
||||
Node::TraitRef(_) => node_str("trait ref"),
|
||||
Node::Pat(_) => node_str("pat"),
|
||||
Node::PatField(_) => node_str("pattern field"),
|
||||
Node::Param(_) => node_str("param"),
|
||||
Node::Arm(_) => node_str("arm"),
|
||||
Node::Block(_) => node_str("block"),
|
||||
Node::Infer(_) => node_str("infer"),
|
||||
Node::Local(_) => node_str("local"),
|
||||
Node::Ctor(ctor) => format!(
|
||||
"{id} (ctor {})",
|
||||
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
|
||||
),
|
||||
Some(Node::Lifetime(_)) => node_str("lifetime"),
|
||||
Some(Node::GenericParam(param)) => {
|
||||
Node::Lifetime(_) => node_str("lifetime"),
|
||||
Node::GenericParam(param) => {
|
||||
format!("{id} (generic_param {})", path_str(param.def_id))
|
||||
}
|
||||
Some(Node::Crate(..)) => String::from("(root_crate)"),
|
||||
None => format!("{id} (unknown node)"),
|
||||
Node::Crate(..) => String::from("(root_crate)"),
|
||||
Node::WhereBoundPredicate(_) => node_str("where bound predicate"),
|
||||
Node::ArrayLenInfer(_) => node_str("array len infer"),
|
||||
Node::Err(_) => node_str("error"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::*;
|
||||
use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP};
|
||||
use rustc_span::{ErrorGuaranteed, ExpnId};
|
||||
|
||||
/// Gather the LocalDefId for each item-like within a module, including items contained within
|
||||
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
|
||||
|
@ -148,10 +148,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
providers.hir_attrs = |tcx, id| {
|
||||
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
|
||||
};
|
||||
providers.def_span = |tcx, def_id| {
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
|
||||
};
|
||||
providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
|
||||
providers.def_ident_span = |tcx, def_id| {
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||
tcx.hir().opt_ident_span(hir_id)
|
||||
|
|
|
@ -1,46 +1,60 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
||||
use crate::ty::{PolyTraitRef, TyCtxt};
|
||||
use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt};
|
||||
|
||||
/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits.
|
||||
/// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition.
|
||||
///
|
||||
/// This only exists in `rustc_middle` because the more powerful elaborator depends on
|
||||
/// `rustc_infer` for elaborating outlives bounds -- this should only be used for pretty
|
||||
/// printing.
|
||||
pub fn super_predicates_for_pretty_printing<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: PolyTraitRef<'tcx>,
|
||||
) -> impl Iterator<Item = Clause<'tcx>> {
|
||||
let clause = trait_ref.to_predicate(tcx);
|
||||
Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] }
|
||||
}
|
||||
|
||||
/// Like [`super_predicates_for_pretty_printing`], except it only returns traits and filters out
|
||||
/// all other [`Clause`]s.
|
||||
pub fn supertraits_for_pretty_printing<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: PolyTraitRef<'tcx>,
|
||||
) -> impl Iterator<Item = PolyTraitRef<'tcx>> {
|
||||
Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] }
|
||||
super_predicates_for_pretty_printing(tcx, trait_ref).filter_map(|clause| {
|
||||
clause.as_trait_clause().map(|trait_clause| trait_clause.to_poly_trait_ref())
|
||||
})
|
||||
}
|
||||
|
||||
struct Elaborator<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
visited: FxHashSet<PolyTraitRef<'tcx>>,
|
||||
stack: Vec<PolyTraitRef<'tcx>>,
|
||||
visited: FxHashSet<Clause<'tcx>>,
|
||||
stack: Vec<Clause<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Elaborator<'tcx> {
|
||||
fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) {
|
||||
let supertrait_refs = self
|
||||
.tcx
|
||||
.super_predicates_of(trait_ref.def_id())
|
||||
.predicates
|
||||
.into_iter()
|
||||
.flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause())
|
||||
.map(|t| t.map_bound(|pred| pred.trait_ref))
|
||||
.filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
|
||||
let super_predicates =
|
||||
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|
||||
|&(pred, _)| {
|
||||
let clause = pred.subst_supertrait(self.tcx, &trait_ref);
|
||||
self.visited.insert(clause).then_some(clause)
|
||||
},
|
||||
);
|
||||
|
||||
self.stack.extend(supertrait_refs);
|
||||
self.stack.extend(super_predicates);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Iterator for Elaborator<'tcx> {
|
||||
type Item = PolyTraitRef<'tcx>;
|
||||
type Item = Clause<'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<PolyTraitRef<'tcx>> {
|
||||
if let Some(trait_ref) = self.stack.pop() {
|
||||
self.elaborate(trait_ref);
|
||||
Some(trait_ref)
|
||||
fn next(&mut self) -> Option<Clause<'tcx>> {
|
||||
if let Some(clause) = self.stack.pop() {
|
||||
if let Some(trait_clause) = clause.as_trait_clause() {
|
||||
self.elaborate(trait_clause.to_poly_trait_ref());
|
||||
}
|
||||
Some(clause)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
|
||||
use crate::query::IntoQueryParam;
|
||||
use crate::query::Providers;
|
||||
use crate::traits::util::supertraits_for_pretty_printing;
|
||||
use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing};
|
||||
use crate::ty::GenericArgKind;
|
||||
use crate::ty::{
|
||||
ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
|
||||
|
@ -1255,8 +1255,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// Generate the main trait ref, including associated types.
|
||||
let mut first = true;
|
||||
|
||||
if let Some(principal) = predicates.principal() {
|
||||
self.wrap_binder(&principal, |principal, cx| {
|
||||
if let Some(bound_principal) = predicates.principal() {
|
||||
self.wrap_binder(&bound_principal, |principal, cx| {
|
||||
define_scoped_cx!(cx);
|
||||
p!(print_def_path(principal.def_id, &[]));
|
||||
|
||||
|
@ -1281,20 +1281,54 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
|
||||
// in order to place the projections inside the `<...>`.
|
||||
if !resugared {
|
||||
// Use a type that can't appear in defaults of type parameters.
|
||||
let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
|
||||
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
|
||||
let principal_with_self =
|
||||
principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
|
||||
|
||||
let args = cx
|
||||
.tcx()
|
||||
.generics_of(principal.def_id)
|
||||
.own_args_no_defaults(cx.tcx(), principal.args);
|
||||
.generics_of(principal_with_self.def_id)
|
||||
.own_args_no_defaults(cx.tcx(), principal_with_self.args);
|
||||
|
||||
let mut projections: Vec<_> = predicates.projection_bounds().collect();
|
||||
projections.sort_by_cached_key(|proj| {
|
||||
cx.tcx().item_name(proj.item_def_id()).to_string()
|
||||
let bound_principal_with_self = bound_principal
|
||||
.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
|
||||
|
||||
let super_projections: Vec<_> =
|
||||
super_predicates_for_pretty_printing(cx.tcx(), bound_principal_with_self)
|
||||
.filter_map(|clause| clause.as_projection_clause())
|
||||
.collect();
|
||||
|
||||
let mut projections: Vec<_> = predicates
|
||||
.projection_bounds()
|
||||
.filter(|&proj| {
|
||||
// Filter out projections that are implied by the super predicates.
|
||||
let proj_is_implied = super_projections.iter().any(|&super_proj| {
|
||||
let super_proj = super_proj.map_bound(|super_proj| {
|
||||
ty::ExistentialProjection::erase_self_ty(cx.tcx(), super_proj)
|
||||
});
|
||||
|
||||
// This function is sometimes called on types with erased and
|
||||
// anonymized regions, but the super projections can still
|
||||
// contain named regions. So we erase and anonymize everything
|
||||
// here to compare the types modulo regions below.
|
||||
let proj = cx.tcx().erase_regions(proj);
|
||||
let proj = cx.tcx().anonymize_bound_vars(proj);
|
||||
let super_proj = cx.tcx().erase_regions(super_proj);
|
||||
let super_proj = cx.tcx().anonymize_bound_vars(super_proj);
|
||||
|
||||
proj == super_proj
|
||||
});
|
||||
!proj_is_implied
|
||||
})
|
||||
.map(|proj| {
|
||||
// Skip the binder, because we don't want to print the binder in
|
||||
// front of the associated item.
|
||||
proj.skip_binder()
|
||||
})
|
||||
.collect();
|
||||
|
||||
projections
|
||||
.sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string());
|
||||
|
||||
if !args.is_empty() || !projections.is_empty() {
|
||||
p!(generic_delimiters(|cx| {
|
||||
cx.comma_sep(args.iter().copied())?;
|
||||
|
|
|
@ -40,55 +40,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&mut self,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) -> bool {
|
||||
// repeatedly simplify match pairs until fixed point is reached
|
||||
debug!("{candidate:#?}");
|
||||
|
||||
// existing_bindings and new_bindings exists to keep the semantics in order.
|
||||
// Reversing the binding order for bindings after `@` changes the binding order in places
|
||||
// it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)`
|
||||
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
||||
// bindings in `pat` before `x`. E.g. (#69971):
|
||||
//
|
||||
// To avoid this, the binding occurs in the following manner:
|
||||
// * the bindings for one iteration of the following loop occurs in order (i.e. left to
|
||||
// right)
|
||||
// * the bindings from the previous iteration of the loop is prepended to the bindings from
|
||||
// the current iteration (in the implementation this is done by mem::swap and extend)
|
||||
// * after all iterations, these new bindings are then appended to the bindings that were
|
||||
// preexisting (i.e. `candidate.binding` when the function was called).
|
||||
//
|
||||
// example:
|
||||
// candidate.bindings = [1, 2, 3]
|
||||
// binding in iter 1: [4, 5]
|
||||
// binding in iter 2: [6, 7]
|
||||
//
|
||||
// final binding: [1, 2, 3, 6, 7, 4, 5]
|
||||
let mut existing_bindings = mem::take(&mut candidate.bindings);
|
||||
let mut new_bindings = Vec::new();
|
||||
loop {
|
||||
let match_pairs = mem::take(&mut candidate.match_pairs);
|
||||
|
||||
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
|
||||
&*match_pairs
|
||||
{
|
||||
existing_bindings.extend_from_slice(&new_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut existing_bindings);
|
||||
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut changed = false;
|
||||
for match_pair in match_pairs {
|
||||
match self.simplify_match_pair(match_pair, candidate) {
|
||||
Ok(()) => {
|
||||
changed = true;
|
||||
}
|
||||
Err(match_pair) => {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Avoid issue #69971: the binding order should be right to left if there are more
|
||||
// bindings after `@` to please the borrow checker
|
||||
// Ex
|
||||
// struct NonCopyStruct {
|
||||
// copy_field: u32,
|
||||
// }
|
||||
|
@ -99,23 +54,67 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// let z = x.copy_field;
|
||||
// let y = x;
|
||||
// }
|
||||
candidate.bindings.extend_from_slice(&new_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut new_bindings);
|
||||
//
|
||||
// We can't just reverse the binding order, because we must preserve pattern-order
|
||||
// otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first,
|
||||
// and bindings at the same depth stay in source order.
|
||||
//
|
||||
// To do this, every time around the loop we prepend the newly found bindings to the
|
||||
// bindings we already had.
|
||||
//
|
||||
// example:
|
||||
// candidate.bindings = [1, 2, 3]
|
||||
// bindings in iter 1: [4, 5]
|
||||
// bindings in iter 2: [6, 7]
|
||||
//
|
||||
// final bindings: [6, 7, 4, 5, 1, 2, 3]
|
||||
let mut accumulated_bindings = mem::take(&mut candidate.bindings);
|
||||
// Repeatedly simplify match pairs until fixed point is reached
|
||||
loop {
|
||||
let mut changed = false;
|
||||
for match_pair in mem::take(&mut candidate.match_pairs) {
|
||||
match self.simplify_match_pair(match_pair, candidate) {
|
||||
Ok(()) => {
|
||||
changed = true;
|
||||
}
|
||||
Err(match_pair) => {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
|
||||
candidate.bindings.extend_from_slice(&accumulated_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
||||
candidate.bindings.clear();
|
||||
|
||||
if !changed {
|
||||
existing_bindings.extend_from_slice(&new_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut existing_bindings);
|
||||
// If we were not able to simplify anymore, done.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Store computed bindings back in `candidate`.
|
||||
mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
|
||||
|
||||
let did_expand_or =
|
||||
if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
|
||||
&*candidate.match_pairs
|
||||
{
|
||||
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
||||
candidate.match_pairs.clear();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Move or-patterns to the end, because they can result in us
|
||||
// creating additional candidates, so we want to test them as
|
||||
// late as possible.
|
||||
candidate
|
||||
.match_pairs
|
||||
.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||
candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
|
||||
debug!(simplified = ?candidate, "simplify_candidate");
|
||||
return false; // if we were not able to simplify any, done.
|
||||
}
|
||||
}
|
||||
|
||||
did_expand_or
|
||||
}
|
||||
|
||||
/// Given `candidate` that has a single or-pattern for its match-pairs,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::fluent_generated as fluent;
|
|||
use rustc_errors::DiagnosticArgValue;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
|
||||
IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage,
|
||||
IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
@ -420,10 +420,7 @@ pub struct UnsafeNotInheritedLintNote {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for UnsafeNotInheritedLintNote {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
|
||||
let body_start = self.body_span.shrink_to_lo();
|
||||
let body_end = self.body_span.shrink_to_hi();
|
||||
|
@ -866,10 +863,7 @@ pub struct Variant {
|
|||
}
|
||||
|
||||
impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.arg("ty", self.ty);
|
||||
let mut spans = MultiSpan::from(self.adt_def_span);
|
||||
|
||||
|
|
|
@ -1231,8 +1231,8 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
|
|||
|
||||
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) {
|
||||
if let Operand::Move(place) = *operand
|
||||
&& let Some(local) = place.as_local()
|
||||
&& self.reused_locals.contains(local)
|
||||
&& !place.is_indirect_first_projection()
|
||||
&& self.reused_locals.contains(place.local)
|
||||
{
|
||||
*operand = Operand::Copy(place);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::borrow::Cow;
|
|||
use rustc_ast::token::Token;
|
||||
use rustc_ast::{Path, Visibility};
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level,
|
||||
SubdiagnosticMessage,
|
||||
codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
|
||||
IntoDiagnostic, Level, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
|
@ -1475,10 +1475,7 @@ pub(crate) struct FnTraitMissingParen {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for FnTraitMissingParen {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
|
||||
let applicability = if self.machine_applicable {
|
||||
Applicability::MachineApplicable
|
||||
|
|
|
@ -827,10 +827,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
self.doc_attr_str_error(meta, "keyword");
|
||||
return false;
|
||||
}
|
||||
match self.tcx.opt_hir_node(hir_id).and_then(|node| match node {
|
||||
let item_kind = match self.tcx.hir_node(hir_id) {
|
||||
hir::Node::Item(item) => Some(&item.kind),
|
||||
_ => None,
|
||||
}) {
|
||||
};
|
||||
match item_kind {
|
||||
Some(ItemKind::Mod(module)) => {
|
||||
if !module.item_ids.is_empty() {
|
||||
self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() });
|
||||
|
@ -853,10 +854,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
|
||||
match self.tcx.opt_hir_node(hir_id).and_then(|node| match node {
|
||||
let item_kind = match self.tcx.hir_node(hir_id) {
|
||||
hir::Node::Item(item) => Some(&item.kind),
|
||||
_ => None,
|
||||
}) {
|
||||
};
|
||||
match item_kind {
|
||||
Some(ItemKind::Impl(i)) => {
|
||||
let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_]))
|
||||
|| if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
|
||||
|
@ -2221,8 +2223,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
} else {
|
||||
// special case when `#[macro_export]` is applied to a macro 2.0
|
||||
let (macro_definition, _) =
|
||||
self.tcx.opt_hir_node(hir_id).unwrap().expect_item().expect_macro();
|
||||
let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro();
|
||||
let is_decl_macro = !macro_definition.macro_rules;
|
||||
|
||||
if is_decl_macro {
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_ast::Label;
|
|||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
|
||||
DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
|
||||
SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_hir::{self as hir, ExprKind, Target};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
|
@ -1753,7 +1754,7 @@ pub struct UnusedVariableStringInterp {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for UnusedVariableStringInterp {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) {
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
|
||||
diag.multipart_suggestion(
|
||||
crate::fluent_generated::passes_string_interpolation_only_works,
|
||||
|
|
|
@ -134,7 +134,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||
Err(hir::LoopIdError::UnresolvedLabel) => None,
|
||||
};
|
||||
|
||||
if let Some(Node::Block(_)) = loop_id.and_then(|id| self.tcx.opt_hir_node(id)) {
|
||||
if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||
|
||||
match destination.target_id {
|
||||
Ok(loop_id) => {
|
||||
if let Node::Block(block) = self.tcx.opt_hir_node(loop_id).unwrap() {
|
||||
if let Node::Block(block) = self.tcx.hir_node(loop_id) {
|
||||
self.sess.dcx().emit_err(ContinueLabeledBlock {
|
||||
span: e.span,
|
||||
block_span: block.span,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
|
||||
use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp};
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::thir::Pat;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
@ -62,10 +62,7 @@ pub struct Overlap<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
let Overlap { span, range } = self;
|
||||
|
||||
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
|
||||
|
|
|
@ -1520,11 +1520,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
|
|||
split_ctors.push(Constructor::Missing);
|
||||
}
|
||||
|
||||
// Decide what constructors to report.
|
||||
let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. });
|
||||
let always_report_all = place.is_scrutinee && !is_integers;
|
||||
// Whether we should report "Enum::A and Enum::C are missing" or "_ is missing".
|
||||
let report_individual_missing_ctors = always_report_all || !all_missing;
|
||||
// Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". At the top
|
||||
// level we prefer to list all constructors.
|
||||
let report_individual_missing_ctors = place.is_scrutinee || !all_missing;
|
||||
// Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() =>
|
||||
// split_ctors.contains(Missing)`. The converse usually holds except when
|
||||
// `!place_validity.is_known_valid()`.
|
||||
|
|
|
@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *};
|
|||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::middle::resolve_bound_vars::Set1;
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::{CrateType, ResolveDocLinks};
|
||||
|
@ -4547,7 +4548,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
if let Some(res) = res
|
||||
&& let Some(def_id) = res.opt_def_id()
|
||||
&& !def_id.is_local()
|
||||
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
|
||||
{
|
||||
if self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
|
||||
&& matches!(
|
||||
self.r.tcx.sess.opts.resolve_doc_links,
|
||||
ResolveDocLinks::ExportedMetadata
|
||||
|
@ -4556,6 +4558,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// Encoding foreign def ids in proc macro crate metadata will ICE.
|
||||
return None;
|
||||
}
|
||||
// Doc paths should be resolved speculatively and should not produce any
|
||||
// diagnostics, but if they are indeed resolved, then we need to keep the
|
||||
// corresponding crate alive.
|
||||
CStore::from_tcx_mut(self.r.tcx).set_used_recursively(def_id.krate);
|
||||
}
|
||||
res
|
||||
});
|
||||
self.r.doc_link_resolutions = doc_link_resolutions;
|
||||
|
|
|
@ -1629,6 +1629,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
self.tcx
|
||||
.sess
|
||||
.time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate)));
|
||||
self.crate_loader(|c| c.unload_unused_crates());
|
||||
});
|
||||
|
||||
// Make sure we don't mutate the cstore from here on.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
|
||||
EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage,
|
||||
EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
|
||||
|
@ -102,10 +102,7 @@ pub enum AdjustSignatureBorrow {
|
|||
}
|
||||
|
||||
impl AddToDiagnostic for AdjustSignatureBorrow {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
match self {
|
||||
AdjustSignatureBorrow::Borrow { to_borrow } => {
|
||||
diag.arg("len", to_borrow.len());
|
||||
|
|
|
@ -19,7 +19,7 @@ use rustc_errors::{
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{Map, Visitor};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::is_range_literal;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
|
||||
|
@ -774,7 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if steps > 0 {
|
||||
// Don't care about `&mut` because `DerefMut` is used less
|
||||
// often and user will not expect that an autoderef happens.
|
||||
if let Some(hir::Node::Expr(hir::Expr {
|
||||
if let hir::Node::Expr(hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::AddrOf(
|
||||
hir::BorrowKind::Ref,
|
||||
|
@ -782,7 +782,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
expr,
|
||||
),
|
||||
..
|
||||
})) = self.tcx.opt_hir_node(*arg_hir_id)
|
||||
}) = self.tcx.hir_node(*arg_hir_id)
|
||||
{
|
||||
let derefs = "*".repeat(steps);
|
||||
err.span_suggestion_verbose(
|
||||
|
@ -1199,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let Res::Local(hir_id) = path.res else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else {
|
||||
let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else {
|
||||
return;
|
||||
};
|
||||
let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
|
||||
|
@ -1786,7 +1786,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
&& let Res::Local(hir_id) = path.res
|
||||
&& let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(hir_id)
|
||||
&& let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id)
|
||||
&& let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id)
|
||||
&& let None = local.ty
|
||||
&& let Some(binding_expr) = local.init
|
||||
|
@ -2198,7 +2198,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let ty::FnPtr(found) = found.kind() else {
|
||||
return;
|
||||
};
|
||||
let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) else {
|
||||
let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else {
|
||||
return;
|
||||
};
|
||||
let hir::ExprKind::Path(path) = arg.kind else {
|
||||
|
@ -3186,8 +3186,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
ObligationCauseCode::VariableType(hir_id) => {
|
||||
let parent_node = tcx.hir().parent_id(hir_id);
|
||||
match tcx.opt_hir_node(parent_node) {
|
||||
Some(Node::Local(hir::Local { ty: Some(ty), .. })) => {
|
||||
match tcx.hir_node(parent_node) {
|
||||
Node::Local(hir::Local { ty: Some(ty), .. }) => {
|
||||
err.span_suggestion_verbose(
|
||||
ty.span.shrink_to_lo(),
|
||||
"consider borrowing here",
|
||||
|
@ -3196,10 +3196,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
err.note("all local variables must have a statically known size");
|
||||
}
|
||||
Some(Node::Local(hir::Local {
|
||||
Node::Local(hir::Local {
|
||||
init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }),
|
||||
..
|
||||
})) => {
|
||||
}) => {
|
||||
// When encountering an assignment of an unsized trait, like
|
||||
// `let x = ""[..];`, provide a suggestion to borrow the initializer in
|
||||
// order to use have a slice instead.
|
||||
|
@ -3211,7 +3211,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
err.note("all local variables must have a statically known size");
|
||||
}
|
||||
Some(Node::Param(param)) => {
|
||||
Node::Param(param) => {
|
||||
err.span_suggestion_verbose(
|
||||
param.ty_span.shrink_to_lo(),
|
||||
"function arguments must have a statically known size, borrowed types \
|
||||
|
@ -3233,7 +3233,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let borrowed_msg = "function arguments must have a statically known size, borrowed \
|
||||
types always have a known size";
|
||||
if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id)
|
||||
&& let hir::Node::Param(param) = self.tcx.hir_node(hir_id)
|
||||
&& let Some(item) = self.tcx.hir().find_parent(hir_id)
|
||||
&& let Some(decl) = item.fn_decl()
|
||||
&& let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span))
|
||||
|
@ -3247,7 +3247,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// param._ty_span
|
||||
ty = Some(t);
|
||||
} else if let Some(hir_id) = hir_id
|
||||
&& let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id)
|
||||
&& let hir::Node::Ty(t) = self.tcx.hir_node(hir_id)
|
||||
{
|
||||
ty = Some(t);
|
||||
}
|
||||
|
@ -3958,7 +3958,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
call_hir_id: HirId,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
if let Some(Node::Expr(expr)) = tcx.opt_hir_node(arg_hir_id)
|
||||
if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
|
||||
&& let Some(typeck_results) = &self.typeck_results
|
||||
{
|
||||
if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
|
||||
|
@ -4074,9 +4074,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
&& let hir::Path { res: Res::Local(hir_id), .. } = path
|
||||
&& let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id)
|
||||
&& let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
|
||||
&& let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id)
|
||||
&& let Some(hir::Node::Local(local)) = self.tcx.opt_hir_node(parent_hir_id)
|
||||
&& let hir::Node::Local(local) = self.tcx.hir_node(parent_hir_id)
|
||||
&& let Some(binding_expr) = local.init
|
||||
{
|
||||
// If the expression we're calling on is a binding, we want to point at the
|
||||
|
@ -4087,17 +4087,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
|
||||
}
|
||||
}
|
||||
let call_node = tcx.opt_hir_node(call_hir_id);
|
||||
if let Some(Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
|
||||
})) = call_node
|
||||
let call_node = tcx.hir_node(call_hir_id);
|
||||
if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) =
|
||||
call_node
|
||||
{
|
||||
if Some(rcvr.span) == err.span.primary_span() {
|
||||
err.replace_span_with(path.ident.span, true);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Node::Expr(expr)) = tcx.opt_hir_node(call_hir_id) {
|
||||
if let Node::Expr(expr) = tcx.hir_node(call_hir_id) {
|
||||
if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
|
||||
| hir::ExprKind::MethodCall(
|
||||
hir::PathSegment { ident: Ident { span, .. }, .. },
|
||||
|
@ -4334,7 +4333,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
&& let hir::Path { res: Res::Local(hir_id), .. } = path
|
||||
&& let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id)
|
||||
&& let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
|
||||
&& let Some(parent) = self.tcx.hir().find_parent(binding.hir_id)
|
||||
{
|
||||
// We've reached the root of the method call chain...
|
||||
|
|
|
@ -993,13 +993,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
&& let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id)
|
||||
&& let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id)
|
||||
&& let arg = arg.peel_borrows()
|
||||
&& let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { res: hir::def::Res::Local(hir_id), .. },
|
||||
)) = arg.kind
|
||||
&& let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id)
|
||||
&& let Node::Pat(pat) = self.tcx.hir_node(*hir_id)
|
||||
&& let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)
|
||||
&& preds.contains(&obligation.predicate)
|
||||
{
|
||||
|
@ -1037,10 +1037,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
|
||||
let body_id = match self.tcx.opt_hir_node(hir_id) {
|
||||
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => {
|
||||
body_id
|
||||
}
|
||||
let body_id = match self.tcx.hir_node(hir_id) {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
|
||||
_ => return false,
|
||||
};
|
||||
let mut v = V { search_span: span, found: None };
|
||||
|
@ -1163,7 +1161,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
&& let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
|
||||
&& let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id)
|
||||
&& let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id)
|
||||
&& let Some(parent) = self.tcx.hir().find_parent(binding.hir_id)
|
||||
{
|
||||
// We've reached the root of the method call chain...
|
||||
|
|
|
@ -82,7 +82,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
|
|||
// but there's already an item with the same namespace and same name. Rust gives
|
||||
// priority to the not-imported one, so we should, too.
|
||||
items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| {
|
||||
// First, lower everything other than imports.
|
||||
// First, lower everything other than glob imports.
|
||||
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<'tcx> SpanMapVisitor<'tcx> {
|
|||
|
||||
/// Used to generate links on items' definition to go to their documentation page.
|
||||
pub(crate) fn extract_info_from_hir_id(&mut self, hir_id: HirId) {
|
||||
if let Some(Node::Item(item)) = self.tcx.opt_hir_node(hir_id) {
|
||||
if let Node::Item(item) = self.tcx.hir_node(hir_id) {
|
||||
if let Some(span) = self.tcx.def_ident_span(item.owner_id) {
|
||||
let cspan = clean::Span::new(span);
|
||||
// If the span isn't from the current crate, we ignore it.
|
||||
|
@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
|||
if !span.overlaps(m.spans.inner_span) {
|
||||
// Now that we confirmed it's a file import, we want to get the span for the module
|
||||
// name only and not all the "mod foo;".
|
||||
if let Some(Node::Item(item)) = self.tcx.opt_hir_node(id) {
|
||||
if let Node::Item(item) = self.tcx.hir_node(id) {
|
||||
self.matches.insert(
|
||||
item.ident.span,
|
||||
LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)),
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res};
|
|||
use rustc_hir::HirId;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_resolve::rustdoc::source_span_for_markdown_range;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use crate::clean::utils::find_nearest_parent_module;
|
||||
|
@ -33,17 +34,22 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
|
|||
return;
|
||||
}
|
||||
|
||||
if item.link_names(&cx.cache).is_empty() {
|
||||
// If there's no link names in this item,
|
||||
// then we skip resolution querying to
|
||||
// avoid from panicking.
|
||||
return;
|
||||
if let Some(item_id) = item.def_id() {
|
||||
check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc);
|
||||
}
|
||||
if let Some(item_id) = item.inline_stmt_id {
|
||||
check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc);
|
||||
}
|
||||
}
|
||||
|
||||
let Some(item_id) = item.def_id() else {
|
||||
return;
|
||||
};
|
||||
let Some(local_item_id) = item_id.as_local() else {
|
||||
fn check_redundant_explicit_link_for_did<'md>(
|
||||
cx: &DocContext<'_>,
|
||||
item: &Item,
|
||||
did: DefId,
|
||||
hir_id: HirId,
|
||||
doc: &'md str,
|
||||
) {
|
||||
let Some(local_item_id) = did.as_local() else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -53,12 +59,26 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
|
|||
return;
|
||||
}
|
||||
let is_private = !cx.render_options.document_private
|
||||
&& !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id);
|
||||
&& !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did);
|
||||
if is_private {
|
||||
return;
|
||||
}
|
||||
|
||||
check_redundant_explicit_link(cx, item, hir_id, &doc);
|
||||
let module_id = match cx.tcx.def_kind(did) {
|
||||
DefKind::Mod if item.inner_docs(cx.tcx) => did,
|
||||
_ => find_nearest_parent_module(cx.tcx, did).unwrap(),
|
||||
};
|
||||
|
||||
let Some(resolutions) =
|
||||
cx.tcx.resolutions(()).doc_link_resolutions.get(&module_id.expect_local())
|
||||
else {
|
||||
// If there's no resolutions in this module,
|
||||
// then we skip resolution querying to
|
||||
// avoid from panicking.
|
||||
return;
|
||||
};
|
||||
|
||||
check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions);
|
||||
}
|
||||
|
||||
fn check_redundant_explicit_link<'md>(
|
||||
|
@ -66,6 +86,7 @@ fn check_redundant_explicit_link<'md>(
|
|||
item: &Item,
|
||||
hir_id: HirId,
|
||||
doc: &'md str,
|
||||
resolutions: &DocLinkResMap,
|
||||
) -> Option<()> {
|
||||
let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
|
||||
let mut offset_iter = Parser::new_with_broken_link_callback(
|
||||
|
@ -74,12 +95,6 @@ fn check_redundant_explicit_link<'md>(
|
|||
Some(&mut broken_line_callback),
|
||||
)
|
||||
.into_offset_iter();
|
||||
let item_id = item.def_id()?;
|
||||
let module_id = match cx.tcx.def_kind(item_id) {
|
||||
DefKind::Mod if item.inner_docs(cx.tcx) => item_id,
|
||||
_ => find_nearest_parent_module(cx.tcx, item_id).unwrap(),
|
||||
};
|
||||
let resolutions = cx.tcx.doc_link_resolutions(module_id);
|
||||
|
||||
while let Some((event, link_range)) = offset_iter.next() {
|
||||
match event {
|
||||
|
|
|
@ -62,7 +62,7 @@ impl LateLintPass<'_> for AbsolutePaths {
|
|||
} = self;
|
||||
|
||||
if !path.span.from_expansion()
|
||||
&& let Some(node) = cx.tcx.opt_hir_node(hir_id)
|
||||
&& let node = cx.tcx.hir_node(hir_id)
|
||||
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
|
||||
&& let [first, rest @ ..] = path.segments
|
||||
// Handle `::std`
|
||||
|
|
|
@ -68,9 +68,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
|
|||
|
||||
fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let map = cx.tcx.hir();
|
||||
if let Some(parent_id) = map.opt_parent_id(expr.hir_id)
|
||||
&& let Some(parent) = cx.tcx.opt_hir_node(parent_id)
|
||||
{
|
||||
if let Some(parent_id) = map.opt_parent_id(expr.hir_id) {
|
||||
let parent = cx.tcx.hir_node(parent_id);
|
||||
let expr = match parent {
|
||||
Node::Block(block) => {
|
||||
if let Some(parent_expr) = block.expr {
|
||||
|
|
|
@ -144,8 +144,7 @@ pub(super) fn check<'tcx>(
|
|||
|
||||
if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
|
||||
if let Some(id) = path_to_local(cast_expr)
|
||||
&& let Some(span) = cx.tcx.hir().opt_span(id)
|
||||
&& !span.eq_ctxt(cast_expr.span)
|
||||
&& !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span)
|
||||
{
|
||||
// Binding context is different than the identifiers context.
|
||||
// Weird macro wizardry could be involved here.
|
||||
|
|
|
@ -195,7 +195,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
|||
&& let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::Default, def_id)
|
||||
&& let impl_item_hir = child.id.hir_id()
|
||||
&& let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir)
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
&& let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
|
||||
&& let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
|
||||
|
|
|
@ -42,7 +42,7 @@ impl LateLintPass<'_> for EmptyDrop {
|
|||
}) = item.kind
|
||||
&& trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
|
||||
&& let impl_item_hir = child.id.hir_id()
|
||||
&& let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir)
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
&& let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
|
||||
&& let func_expr = peel_blocks(func_expr)
|
||||
|
|
|
@ -123,11 +123,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
|
|||
|
||||
// TODO: Replace with Map::is_argument(..) when it's fixed
|
||||
fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||
match tcx.opt_hir_node(id) {
|
||||
Some(Node::Pat(Pat {
|
||||
match tcx.hir_node(id) {
|
||||
Node::Pat(Pat {
|
||||
kind: PatKind::Binding(..),
|
||||
..
|
||||
})) => (),
|
||||
}) => (),
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>)
|
|||
// Find id of the local that expr_end_of_block resolves to
|
||||
&& let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind
|
||||
&& let Res::Local(expr_res) = expr_path.res
|
||||
&& let Some(Node::Pat(res_pat)) = cx.tcx.opt_hir_node(expr_res)
|
||||
&& let Node::Pat(res_pat) = cx.tcx.hir_node(expr_res)
|
||||
|
||||
// Find id of the local we found in the block
|
||||
&& let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind
|
||||
|
|
|
@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
|
|||
|
||||
// Checking for slice indexing
|
||||
&& let parent_id = map.parent_id(expr.hir_id)
|
||||
&& let Some(hir::Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id)
|
||||
&& let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id)
|
||||
&& let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind
|
||||
&& let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr)
|
||||
&& let Ok(index_value) = index_value.try_into()
|
||||
|
@ -256,7 +256,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
|
|||
|
||||
// Make sure that this slice index is read only
|
||||
&& let maybe_addrof_id = map.parent_id(parent_id)
|
||||
&& let Some(hir::Node::Expr(maybe_addrof_expr)) = cx.tcx.opt_hir_node(maybe_addrof_id)
|
||||
&& let hir::Node::Expr(maybe_addrof_expr) = cx.tcx.hir_node(maybe_addrof_id)
|
||||
&& let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind
|
||||
{
|
||||
use_info.index_use.push((index_value, map.span(parent_expr.hir_id)));
|
||||
|
|
|
@ -147,9 +147,9 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
|||
&& let Some(output) =
|
||||
parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder())
|
||||
{
|
||||
let (name, kind) = match cx.tcx.opt_hir_node(ty_hir_id) {
|
||||
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
|
||||
Some(Node::Item(x)) => match x.kind {
|
||||
let (name, kind) = match cx.tcx.hir_node(ty_hir_id) {
|
||||
Node::ForeignItem(x) => (x.ident.name, "extern type"),
|
||||
Node::Item(x) => match x.kind {
|
||||
ItemKind::Struct(..) => (x.ident.name, "struct"),
|
||||
ItemKind::Enum(..) => (x.ident.name, "enum"),
|
||||
ItemKind::Union(..) => (x.ident.name, "union"),
|
||||
|
|
|
@ -63,7 +63,7 @@ pub(super) fn check<'tcx>(
|
|||
&& let PatKind::Binding(bind_ann, ..) = pat.kind
|
||||
&& !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut))
|
||||
&& let parent_node = cx.tcx.hir().parent_id(hir_id)
|
||||
&& let Some(Node::Local(parent_let_expr)) = cx.tcx.opt_hir_node(parent_node)
|
||||
&& let Node::Local(parent_let_expr) = cx.tcx.hir_node(parent_node)
|
||||
&& let Some(init) = parent_let_expr.init
|
||||
{
|
||||
match init.kind {
|
||||
|
|
|
@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
|
|||
// Also ensures the const is nonzero since zero can't be a divisor
|
||||
&& const1 == const2 && const2 == const3
|
||||
&& let Some(hir_id) = path_to_local(expr3)
|
||||
&& let Some(Node::Pat(_)) = cx.tcx.opt_hir_node(hir_id)
|
||||
&& let Node::Pat(_) = cx.tcx.hir_node(hir_id)
|
||||
{
|
||||
// Apply only to params or locals with annotated types
|
||||
match cx.tcx.hir().find_parent(hir_id) {
|
||||
|
|
|
@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
|
|||
// add note if not multi-line
|
||||
span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| {
|
||||
let (applicability, pat) = if let Some(id) = path_to_local(recv)
|
||||
&& let Some(hir::Node::Pat(pat)) = cx.tcx.opt_hir_node(id)
|
||||
&& let hir::Node::Pat(pat) = cx.tcx.hir_node(id)
|
||||
&& let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind
|
||||
{
|
||||
(Applicability::Unspecified, Some((pat.span, ident)))
|
||||
|
|
|
@ -135,7 +135,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
|
|||
|
||||
fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) {
|
||||
if let Res::Local(local_id) = path.res
|
||||
&& let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id)
|
||||
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
|
||||
&& let PatKind::Binding(_, local_id, ..) = pat.kind
|
||||
{
|
||||
self.identifiers.insert(local_id);
|
||||
|
@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
|
|||
&& let ExprKind::Path(ref path) = expr.kind
|
||||
&& let QPath::Resolved(_, path) = path
|
||||
&& let Res::Local(local_id) = path.res
|
||||
&& let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id)
|
||||
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
|
||||
&& let PatKind::Binding(_, local_id, ..) = pat.kind
|
||||
&& self.identifiers.contains(&local_id)
|
||||
{
|
||||
|
|
|
@ -91,10 +91,10 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
|
|||
let node = if hir_id.local_id == ItemLocalId::from_u32(0) {
|
||||
// In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't
|
||||
// reimplement it even if we wanted to
|
||||
cx.tcx.opt_hir_node(hir_id)
|
||||
Some(cx.tcx.hir_node(hir_id))
|
||||
} else {
|
||||
let owner = cx.tcx.hir_owner_nodes(hir_id.owner);
|
||||
owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node)
|
||||
owner.nodes.get(hir_id.local_id).copied().map(|p| p.node)
|
||||
};
|
||||
let Some(node) = node else {
|
||||
return;
|
||||
|
|
|
@ -213,11 +213,8 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
|
|||
if parent_id == cur_id {
|
||||
break;
|
||||
}
|
||||
let Some(parent_node) = vis.cx.tcx.opt_hir_node(parent_id) else {
|
||||
break;
|
||||
};
|
||||
|
||||
let stop_early = match parent_node {
|
||||
let stop_early = match vis.cx.tcx.hir_node(parent_id) {
|
||||
Node::Expr(expr) => check_expr(vis, expr),
|
||||
Node::Stmt(stmt) => check_stmt(vis, stmt),
|
||||
Node::Item(_) => {
|
||||
|
|
|
@ -453,7 +453,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
|
|||
if parent_id == cur_expr.hir_id {
|
||||
break;
|
||||
}
|
||||
if let Some(Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) {
|
||||
if let Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) {
|
||||
match &parent_expr.kind {
|
||||
ExprKind::AddrOf(..) => {
|
||||
// `&e` => `e` must be referenced.
|
||||
|
|
|
@ -76,8 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|
|||
match of_trait {
|
||||
Some(trait_ref) => {
|
||||
let mut methods_in_trait: BTreeSet<Symbol> =
|
||||
if let Some(Node::TraitRef(TraitRef { path, .. })) =
|
||||
cx.tcx.opt_hir_node(trait_ref.hir_ref_id)
|
||||
if let Node::TraitRef(TraitRef { path, .. }) =
|
||||
cx.tcx.hir_node(trait_ref.hir_ref_id)
|
||||
&& let Res::Def(DefKind::Trait, did) = path.res
|
||||
{
|
||||
// FIXME: if
|
||||
|
|
|
@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
|
|||
if let Some(self_def) = self_ty.ty_adt_def()
|
||||
&& let Some(self_local_did) = self_def.did().as_local()
|
||||
&& let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did)
|
||||
&& let Some(Node::Item(x)) = cx.tcx.opt_hir_node(self_id)
|
||||
&& let Node::Item(x) = cx.tcx.hir_node(self_id)
|
||||
&& let type_name = x.ident.name.as_str().to_lowercase()
|
||||
&& (impl_item.ident.name.as_str() == type_name
|
||||
|| impl_item.ident.name.as_str().replace('_', "") == type_name)
|
||||
|
|
|
@ -177,10 +177,10 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr
|
|||
/// canonical binding `HirId`.
|
||||
pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
|
||||
let hir = cx.tcx.hir();
|
||||
if let Some(Node::Pat(pat)) = cx.tcx.opt_hir_node(hir_id)
|
||||
if let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
|
||||
&& matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..))
|
||||
&& let parent = hir.parent_id(hir_id)
|
||||
&& let Some(Node::Local(local)) = cx.tcx.opt_hir_node(parent)
|
||||
&& let Node::Local(local) = cx.tcx.hir_node(parent)
|
||||
{
|
||||
return local.init;
|
||||
}
|
||||
|
@ -1327,7 +1327,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
|
|||
let map = &cx.tcx.hir();
|
||||
let enclosing_node = map
|
||||
.get_enclosing_scope(hir_id)
|
||||
.and_then(|enclosing_id| cx.tcx.opt_hir_node(enclosing_id));
|
||||
.map(|enclosing_id| cx.tcx.hir_node(enclosing_id));
|
||||
enclosing_node.and_then(|node| match node {
|
||||
Node::Block(block) => Some(block),
|
||||
Node::Item(&Item {
|
||||
|
@ -2696,10 +2696,10 @@ impl<'tcx> ExprUseNode<'tcx> {
|
|||
)),
|
||||
Self::Return(id) => {
|
||||
let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id);
|
||||
if let Some(Node::Expr(Expr {
|
||||
if let Node::Expr(Expr {
|
||||
kind: ExprKind::Closure(c),
|
||||
..
|
||||
})) = cx.tcx.opt_hir_node(hir_id)
|
||||
}) = cx.tcx.hir_node(hir_id)
|
||||
{
|
||||
match c.fn_decl.output {
|
||||
FnRetTy::DefaultReturn(_) => None,
|
||||
|
|
|
@ -51,13 +51,13 @@
|
|||
- }
|
||||
-
|
||||
- bb3: {
|
||||
StorageLive(_8);
|
||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_8);
|
||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
_0 = const 0_u32;
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_9);
|
||||
- goto -> bb4;
|
||||
+ goto -> bb3;
|
||||
}
|
||||
|
|
|
@ -58,13 +58,13 @@
|
|||
-
|
||||
- bb4: {
|
||||
+ bb2: {
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_10);
|
||||
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
_0 = const 0_u32;
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_10);
|
||||
- goto -> bb6;
|
||||
+ goto -> bb4;
|
||||
}
|
||||
|
|
|
@ -51,13 +51,13 @@
|
|||
- }
|
||||
-
|
||||
- bb3: {
|
||||
StorageLive(_8);
|
||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
|
||||
StorageLive(_8);
|
||||
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
_0 = const 0_u32;
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_9);
|
||||
- goto -> bb4;
|
||||
+ goto -> bb3;
|
||||
}
|
||||
|
|
|
@ -69,16 +69,16 @@
|
|||
|
||||
- bb4: {
|
||||
+ bb3: {
|
||||
StorageLive(_11);
|
||||
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_12);
|
||||
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_13);
|
||||
_13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_12);
|
||||
_12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_11);
|
||||
_11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
|
||||
_0 = const 0_u32;
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
StorageDead(_11);
|
||||
StorageDead(_12);
|
||||
StorageDead(_13);
|
||||
- goto -> bb5;
|
||||
+ goto -> bb4;
|
||||
}
|
||||
|
|
|
@ -116,12 +116,12 @@
|
|||
}
|
||||
|
||||
bb6: {
|
||||
StorageLive(_12);
|
||||
_39 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_12 = (((*_39) as Vw).0: f32);
|
||||
StorageLive(_13);
|
||||
_40 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_13 = (((*_40) as Vw).0: f32);
|
||||
_39 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_13 = (((*_39) as Vw).0: f32);
|
||||
StorageLive(_12);
|
||||
_40 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_12 = (((*_40) as Vw).0: f32);
|
||||
StorageLive(_14);
|
||||
StorageLive(_15);
|
||||
_15 = _12;
|
||||
|
@ -132,18 +132,18 @@
|
|||
StorageDead(_15);
|
||||
_3 = ViewportPercentageLength::Vw(move _14);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
StorageDead(_13);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageLive(_17);
|
||||
_41 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_17 = (((*_41) as Vh).0: f32);
|
||||
StorageLive(_18);
|
||||
_42 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_18 = (((*_42) as Vh).0: f32);
|
||||
_41 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_18 = (((*_41) as Vh).0: f32);
|
||||
StorageLive(_17);
|
||||
_42 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_17 = (((*_42) as Vh).0: f32);
|
||||
StorageLive(_19);
|
||||
StorageLive(_20);
|
||||
_20 = _17;
|
||||
|
@ -154,18 +154,18 @@
|
|||
StorageDead(_20);
|
||||
_3 = ViewportPercentageLength::Vh(move _19);
|
||||
StorageDead(_19);
|
||||
StorageDead(_18);
|
||||
StorageDead(_17);
|
||||
StorageDead(_18);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
StorageLive(_22);
|
||||
_43 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_22 = (((*_43) as Vmin).0: f32);
|
||||
StorageLive(_23);
|
||||
_44 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_23 = (((*_44) as Vmin).0: f32);
|
||||
_43 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_23 = (((*_43) as Vmin).0: f32);
|
||||
StorageLive(_22);
|
||||
_44 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_22 = (((*_44) as Vmin).0: f32);
|
||||
StorageLive(_24);
|
||||
StorageLive(_25);
|
||||
_25 = _22;
|
||||
|
@ -176,18 +176,18 @@
|
|||
StorageDead(_25);
|
||||
_3 = ViewportPercentageLength::Vmin(move _24);
|
||||
StorageDead(_24);
|
||||
StorageDead(_23);
|
||||
StorageDead(_22);
|
||||
StorageDead(_23);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageLive(_27);
|
||||
_45 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_27 = (((*_45) as Vmax).0: f32);
|
||||
StorageLive(_28);
|
||||
_46 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_28 = (((*_46) as Vmax).0: f32);
|
||||
_45 = deref_copy (_4.1: &ViewportPercentageLength);
|
||||
_28 = (((*_45) as Vmax).0: f32);
|
||||
StorageLive(_27);
|
||||
_46 = deref_copy (_4.0: &ViewportPercentageLength);
|
||||
_27 = (((*_46) as Vmax).0: f32);
|
||||
StorageLive(_29);
|
||||
StorageLive(_30);
|
||||
_30 = _27;
|
||||
|
@ -198,8 +198,8 @@
|
|||
StorageDead(_30);
|
||||
_3 = ViewportPercentageLength::Vmax(move _29);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
StorageDead(_27);
|
||||
StorageDead(_28);
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,13 +59,13 @@
|
|||
}
|
||||
|
||||
bb5: {
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_10);
|
||||
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
|
||||
StorageLive(_9);
|
||||
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
|
||||
_0 = const 0_u32;
|
||||
StorageDead(_10);
|
||||
StorageDead(_9);
|
||||
StorageDead(_10);
|
||||
goto -> bb8;
|
||||
}
|
||||
|
||||
|
|
27
tests/mir-opt/gvn_copy_moves.fn0.GVN.diff
Normal file
27
tests/mir-opt/gvn_copy_moves.fn0.GVN.diff
Normal file
|
@ -0,0 +1,27 @@
|
|||
- // MIR for `fn0` before GVN
|
||||
+ // MIR for `fn0` after GVN
|
||||
|
||||
fn fn0() -> () {
|
||||
let mut _0: ();
|
||||
let mut _1: usize;
|
||||
let mut _2: [u128; 6];
|
||||
let mut _3: ([u128; 6],);
|
||||
let mut _4: ([u128; 6],);
|
||||
let mut _5: ();
|
||||
|
||||
bb0: {
|
||||
_1 = const 1_usize;
|
||||
_2 = [const 42_u128; 6];
|
||||
- _2[_1] = const 1_u128;
|
||||
+ _2[1 of 2] = const 1_u128;
|
||||
_3 = (_2,);
|
||||
_4 = _3;
|
||||
- _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable];
|
||||
+ _5 = fn1((_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
46
tests/mir-opt/gvn_copy_moves.rs
Normal file
46
tests/mir-opt/gvn_copy_moves.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
// unit-test: GVN
|
||||
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "initial")]
|
||||
fn fn0() {
|
||||
// CHECK-LABEL: fn fn0(
|
||||
mir! {
|
||||
let a: usize;
|
||||
let b: [u128; 6];
|
||||
let c: ([u128; 6],);
|
||||
let d: ([u128; 6],);
|
||||
let x: ();
|
||||
{
|
||||
// CHECK: bb0: {
|
||||
// CHECK-NEXT: _1 = const 1_usize;
|
||||
// CHECK-NEXT: _2 = [const 42_u128; 6];
|
||||
// CHECK-NEXT: _2[1 of 2] = const 1_u128;
|
||||
// CHECK-NEXT: _3 = (_2,);
|
||||
// CHECK-NEXT: _4 = _3;
|
||||
// CHECK-NEXT: _5 = fn1((_3.0: [u128; 6]), _3)
|
||||
a = 1_usize;
|
||||
b = [42; 6];
|
||||
b[a] = 1;
|
||||
c = (b,);
|
||||
d = c;
|
||||
Call(x = fn1(Move(c.0), d), ReturnTo(bb1), UnwindUnreachable())
|
||||
}
|
||||
bb1 = {
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn fn1(a: [u128; 6], mut b: ([u128; 6],)) {
|
||||
b.0 = [0; 6];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn0();
|
||||
}
|
||||
|
||||
// EMIT_MIR gvn_copy_moves.fn0.GVN.diff
|
|
@ -66,7 +66,7 @@
|
|||
_5 = ((_2 as Break).0: std::result::Result<std::convert::Infallible, i32>);
|
||||
StorageLive(_6);
|
||||
_6 = _5;
|
||||
_12 = move ((_5 as Err).0: i32);
|
||||
_12 = ((_5 as Err).0: i32);
|
||||
_0 = Result::<i32, i32>::Err(_12);
|
||||
StorageDead(_6);
|
||||
StorageDead(_2);
|
||||
|
@ -83,7 +83,7 @@
|
|||
}
|
||||
|
||||
bb4: {
|
||||
_10 = move ((_1 as Err).0: i32);
|
||||
_10 = ((_1 as Err).0: i32);
|
||||
StorageLive(_11);
|
||||
_11 = Result::<Infallible, i32>::Err(_10);
|
||||
_2 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _11);
|
||||
|
@ -92,7 +92,7 @@
|
|||
}
|
||||
|
||||
bb5: {
|
||||
_9 = move ((_1 as Ok).0: i32);
|
||||
_9 = ((_1 as Ok).0: i32);
|
||||
_2 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(_9);
|
||||
goto -> bb3;
|
||||
}
|
||||
|
|
17
tests/rustdoc-ui/issues/issue-120444-1.rs
Normal file
17
tests/rustdoc-ui/issues/issue-120444-1.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// compile-flags: --document-private-items
|
||||
|
||||
#![deny(rustdoc::redundant_explicit_links)]
|
||||
|
||||
mod webdavfs {
|
||||
pub struct A;
|
||||
pub struct B;
|
||||
}
|
||||
|
||||
/// [`Vfs`][crate::Vfs]
|
||||
pub use webdavfs::A;
|
||||
//~^^ error: redundant explicit link target
|
||||
|
||||
/// [`Vfs`]
|
||||
pub use webdavfs::B;
|
||||
|
||||
pub struct Vfs;
|
22
tests/rustdoc-ui/issues/issue-120444-1.stderr
Normal file
22
tests/rustdoc-ui/issues/issue-120444-1.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error: redundant explicit link target
|
||||
--> $DIR/issue-120444-1.rs:10:13
|
||||
|
|
||||
LL | /// [`Vfs`][crate::Vfs]
|
||||
| ----- ^^^^^^^^^^ explicit target is redundant
|
||||
| |
|
||||
| because label contains path that resolves to same destination
|
||||
|
|
||||
= note: when a link's destination is not specified,
|
||||
the label is used to resolve intra-doc links
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-120444-1.rs:3:9
|
||||
|
|
||||
LL | #![deny(rustdoc::redundant_explicit_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: remove explicit link target
|
||||
|
|
||||
LL | /// [`Vfs`]
|
||||
| ~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
17
tests/rustdoc-ui/issues/issue-120444-2.rs
Normal file
17
tests/rustdoc-ui/issues/issue-120444-2.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// compile-flags: --document-private-items
|
||||
|
||||
#![deny(rustdoc::redundant_explicit_links)]
|
||||
|
||||
pub mod webdavfs {
|
||||
pub struct A;
|
||||
pub struct B;
|
||||
}
|
||||
|
||||
/// [`Vfs`][crate::Vfs]
|
||||
pub use webdavfs::A;
|
||||
//~^^ error: redundant explicit link target
|
||||
|
||||
/// [`Vfs`]
|
||||
pub use webdavfs::B;
|
||||
|
||||
pub struct Vfs;
|
22
tests/rustdoc-ui/issues/issue-120444-2.stderr
Normal file
22
tests/rustdoc-ui/issues/issue-120444-2.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error: redundant explicit link target
|
||||
--> $DIR/issue-120444-2.rs:10:13
|
||||
|
|
||||
LL | /// [`Vfs`][crate::Vfs]
|
||||
| ----- ^^^^^^^^^^ explicit target is redundant
|
||||
| |
|
||||
| because label contains path that resolves to same destination
|
||||
|
|
||||
= note: when a link's destination is not specified,
|
||||
the label is used to resolve intra-doc links
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-120444-2.rs:3:9
|
||||
|
|
||||
LL | #![deny(rustdoc::redundant_explicit_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: remove explicit link target
|
||||
|
|
||||
LL | /// [`Vfs`]
|
||||
| ~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -14,7 +14,7 @@ extern crate rustc_span;
|
|||
|
||||
use rustc_errors::{
|
||||
AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt,
|
||||
IntoDiagnostic, Level, SubdiagnosticMessage,
|
||||
IntoDiagnostic, Level, SubdiagnosticMessageOp,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
|
@ -55,9 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn
|
|||
pub struct UntranslatableInAddToDiagnostic;
|
||||
|
||||
impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F)
|
||||
{
|
||||
diag.note("untranslatable diagnostic");
|
||||
//~^ ERROR diagnostics should be created using translatable messages
|
||||
|
@ -67,10 +65,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
|
|||
pub struct TranslatableInAddToDiagnostic;
|
||||
|
||||
impl AddToDiagnostic for TranslatableInAddToDiagnostic {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
||||
diag.note(crate::fluent_generated::no_crate_note);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: diagnostics should be created using translatable messages
|
||||
--> $DIR/diagnostics.rs:62:14
|
||||
--> $DIR/diagnostics.rs:60:14
|
||||
|
|
||||
LL | diag.note("untranslatable diagnostic");
|
||||
| ^^^^
|
||||
|
||||
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
||||
--> $DIR/diagnostics.rs:79:21
|
||||
--> $DIR/diagnostics.rs:74:21
|
||||
|
|
||||
LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
|
||||
| ^^^^^^^^^^
|
||||
|
@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
||||
--> $DIR/diagnostics.rs:82:21
|
||||
--> $DIR/diagnostics.rs:77:21
|
||||
|
|
||||
LL | let _diag = dcx.struct_err("untranslatable diagnostic");
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: diagnostics should be created using translatable messages
|
||||
--> $DIR/diagnostics.rs:82:21
|
||||
--> $DIR/diagnostics.rs:77:21
|
||||
|
|
||||
LL | let _diag = dcx.struct_err("untranslatable diagnostic");
|
||||
| ^^^^^^^^^^
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
// edition: 2021
|
||||
// check-pass
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
trait MyTrait {
|
||||
#[allow(async_fn_in_trait)]
|
||||
pub trait MyTrait {
|
||||
async fn foo(&self) -> i32;
|
||||
}
|
||||
|
||||
impl MyTrait for i32 {
|
||||
#[warn(refining_impl_trait)]
|
||||
fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
|
||||
//~^ ERROR method `foo` should be async
|
||||
//~^ WARN impl trait in impl method signature does not match trait method signature
|
||||
Box::pin(async { *self })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
error: method `foo` should be async because the method from the trait is async
|
||||
--> $DIR/async-example-desugared-boxed.rs:11:5
|
||||
warning: impl trait in impl method signature does not match trait method signature
|
||||
--> $DIR/async-example-desugared-boxed.rs:14:22
|
||||
|
|
||||
LL | async fn foo(&self) -> i32;
|
||||
| --------------------------- required because the trait method is async
|
||||
| --------------------------- return type from trait method defined here
|
||||
...
|
||||
LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
|
||||
note: the lint level is defined here
|
||||
--> $DIR/async-example-desugared-boxed.rs:13:12
|
||||
|
|
||||
LL | #[warn(refining_impl_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
help: replace the return type so that it matches the trait
|
||||
|
|
||||
LL | fn foo(&self) -> impl Future<Output = i32> {
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
// edition: 2021
|
||||
// check-pass
|
||||
|
||||
use std::future::Future;
|
||||
use std::task::Poll;
|
||||
|
||||
trait MyTrait {
|
||||
#[allow(async_fn_in_trait)]
|
||||
pub trait MyTrait {
|
||||
async fn foo(&self) -> i32;
|
||||
}
|
||||
|
||||
struct MyFuture;
|
||||
pub struct MyFuture;
|
||||
impl Future for MyFuture {
|
||||
type Output = i32;
|
||||
fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||
|
@ -16,8 +18,9 @@ impl Future for MyFuture {
|
|||
}
|
||||
|
||||
impl MyTrait for u32 {
|
||||
#[warn(refining_impl_trait)]
|
||||
fn foo(&self) -> MyFuture {
|
||||
//~^ ERROR method `foo` should be async
|
||||
//~^ WARN impl trait in impl method signature does not match trait method signature
|
||||
MyFuture
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue