Auto merge of #144469 - Kivooeo:chains-cleanup, r=SparrowLii
Some `let chains` clean-up Not sure if this kind of clean-up is welcoming because of size, but I decided to try out one r? compiler
This commit is contained in:
commit
d242a8bd5a
77 changed files with 1115 additions and 1209 deletions
|
|
@ -164,11 +164,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
fn visit_item(&mut self, i: &'hir Item<'hir>) {
|
||||
debug_assert_eq!(i.owner_id, self.owner);
|
||||
self.with_parent(i.hir_id(), |this| {
|
||||
if let ItemKind::Struct(_, _, struct_def) = &i.kind {
|
||||
if let ItemKind::Struct(_, _, struct_def) = &i.kind
|
||||
// If this is a tuple or unit-like struct, register the constructor.
|
||||
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
|
||||
this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
|
||||
}
|
||||
&& let Some(ctor_hir_id) = struct_def.ctor_hir_id()
|
||||
{
|
||||
this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
|
||||
}
|
||||
intravisit::walk_item(this, i);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -640,16 +640,16 @@ impl<'a> AstValidator<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(header) = fk.header() {
|
||||
if let Const::Yes(const_span) = header.constness {
|
||||
let mut spans = variadic_spans.clone();
|
||||
spans.push(const_span);
|
||||
self.dcx().emit_err(errors::ConstAndCVariadic {
|
||||
spans,
|
||||
const_span,
|
||||
variadic_spans: variadic_spans.clone(),
|
||||
});
|
||||
}
|
||||
if let Some(header) = fk.header()
|
||||
&& let Const::Yes(const_span) = header.constness
|
||||
{
|
||||
let mut spans = variadic_spans.clone();
|
||||
spans.push(const_span);
|
||||
self.dcx().emit_err(errors::ConstAndCVariadic {
|
||||
spans,
|
||||
const_span,
|
||||
variadic_spans: variadic_spans.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
match (fk.ctxt(), fk.header()) {
|
||||
|
|
|
|||
|
|
@ -630,16 +630,11 @@ fn check_incompatible_features(sess: &Session, features: &Features) {
|
|||
.iter()
|
||||
.filter(|(f1, f2)| features.enabled(*f1) && features.enabled(*f2))
|
||||
{
|
||||
if let Some((f1_name, f1_span)) = enabled_features.clone().find(|(name, _)| name == f1) {
|
||||
if let Some((f2_name, f2_span)) = enabled_features.clone().find(|(name, _)| name == f2)
|
||||
{
|
||||
let spans = vec![f1_span, f2_span];
|
||||
sess.dcx().emit_err(errors::IncompatibleFeatures {
|
||||
spans,
|
||||
f1: f1_name,
|
||||
f2: f2_name,
|
||||
});
|
||||
}
|
||||
if let Some((f1_name, f1_span)) = enabled_features.clone().find(|(name, _)| name == f1)
|
||||
&& let Some((f2_name, f2_span)) = enabled_features.clone().find(|(name, _)| name == f2)
|
||||
{
|
||||
let spans = vec![f1_span, f2_span];
|
||||
sess.dcx().emit_err(errors::IncompatibleFeatures { spans, f1: f1_name, f2: f2_name });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -572,10 +572,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
}
|
||||
|
||||
fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option<BytePos>) {
|
||||
if let Some(cmnts) = self.comments_mut() {
|
||||
if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
|
||||
self.print_comment(cmnt);
|
||||
}
|
||||
if let Some(cmnts) = self.comments_mut()
|
||||
&& let Some(cmnt) = cmnts.trailing_comment(span, next_pos)
|
||||
{
|
||||
self.print_comment(cmnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2533,13 +2533,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
|
||||
// Check that the parent of the closure is a method call,
|
||||
// with receiver matching with local's type (modulo refs)
|
||||
if let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_expr.hir_id) {
|
||||
if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
|
||||
let recv_ty = typeck_results.expr_ty(recv);
|
||||
if let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_expr.hir_id)
|
||||
&& let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind
|
||||
{
|
||||
let recv_ty = typeck_results.expr_ty(recv);
|
||||
|
||||
if recv_ty.peel_refs() != local_ty {
|
||||
return;
|
||||
}
|
||||
if recv_ty.peel_refs() != local_ty {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2805,16 +2805,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
// With the place of a union and a field access into it, we traverse the second
|
||||
// borrowed place and look for an access to a different field of the same union.
|
||||
for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
|
||||
if let ProjectionElem::Field(field, _) = elem {
|
||||
if let Some(union_ty) = union_ty(place_base) {
|
||||
if field != target_field && place_base == target_base {
|
||||
return Some((
|
||||
self.describe_any_place(place_base),
|
||||
self.describe_any_place(first_borrowed_place.as_ref()),
|
||||
self.describe_any_place(second_borrowed_place.as_ref()),
|
||||
union_ty.to_string(),
|
||||
));
|
||||
}
|
||||
if let ProjectionElem::Field(field, _) = elem
|
||||
&& let Some(union_ty) = union_ty(place_base)
|
||||
{
|
||||
if field != target_field && place_base == target_base {
|
||||
return Some((
|
||||
self.describe_any_place(place_base),
|
||||
self.describe_any_place(first_borrowed_place.as_ref()),
|
||||
self.describe_any_place(second_borrowed_place.as_ref()),
|
||||
union_ty.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3001,16 +3001,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
from_closure: false,
|
||||
..
|
||||
} = explanation
|
||||
{
|
||||
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
&& let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
borrow,
|
||||
borrow_span,
|
||||
span,
|
||||
category,
|
||||
opt_place_desc.as_ref(),
|
||||
) {
|
||||
return diag;
|
||||
}
|
||||
)
|
||||
{
|
||||
return diag;
|
||||
}
|
||||
|
||||
let name = format!("`{name}`");
|
||||
|
|
@ -3772,30 +3771,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
let loan_span = loan_spans.args_or_use();
|
||||
|
||||
let descr_place = self.describe_any_place(place.as_ref());
|
||||
if let BorrowKind::Fake(_) = loan.kind {
|
||||
if let Some(section) = self.classify_immutable_section(loan.assigned_place) {
|
||||
let mut err = self.cannot_mutate_in_immutable_section(
|
||||
span,
|
||||
loan_span,
|
||||
&descr_place,
|
||||
section,
|
||||
"assign",
|
||||
);
|
||||
if let BorrowKind::Fake(_) = loan.kind
|
||||
&& let Some(section) = self.classify_immutable_section(loan.assigned_place)
|
||||
{
|
||||
let mut err = self.cannot_mutate_in_immutable_section(
|
||||
span,
|
||||
loan_span,
|
||||
&descr_place,
|
||||
section,
|
||||
"assign",
|
||||
);
|
||||
|
||||
loan_spans.var_subdiag(&mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
|
||||
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
|
||||
BorrowUseInClosure { var_span }
|
||||
}
|
||||
loan_spans.var_subdiag(&mut err, Some(loan.kind), |kind, var_span| {
|
||||
use crate::session_diagnostics::CaptureVarCause::*;
|
||||
match kind {
|
||||
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
|
||||
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
|
||||
BorrowUseInClosure { var_span }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
self.buffer_error(err);
|
||||
self.buffer_error(err);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
|
||||
|
|
@ -4048,119 +4047,116 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
"annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
|
||||
target, stmt
|
||||
);
|
||||
if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind {
|
||||
if let Some(assigned_to) = place.as_local() {
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_to={:?} \
|
||||
if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
|
||||
&& let Some(assigned_to) = place.as_local()
|
||||
{
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_to={:?} \
|
||||
rvalue={:?}",
|
||||
assigned_to, rvalue
|
||||
);
|
||||
// Check if our `target` was captured by a closure.
|
||||
if let Rvalue::Aggregate(
|
||||
box AggregateKind::Closure(def_id, args),
|
||||
operands,
|
||||
) = rvalue
|
||||
{
|
||||
let def_id = def_id.expect_local();
|
||||
for operand in operands {
|
||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
|
||||
operand
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_from={:?}",
|
||||
assigned_from
|
||||
);
|
||||
assigned_to, rvalue
|
||||
);
|
||||
// Check if our `target` was captured by a closure.
|
||||
if let Rvalue::Aggregate(box AggregateKind::Closure(def_id, args), operands) =
|
||||
rvalue
|
||||
{
|
||||
let def_id = def_id.expect_local();
|
||||
for operand in operands {
|
||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
|
||||
operand
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_from={:?}",
|
||||
assigned_from
|
||||
);
|
||||
|
||||
// Find the local from the operand.
|
||||
let Some(assigned_from_local) =
|
||||
assigned_from.local_or_deref_local()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
// Find the local from the operand.
|
||||
let Some(assigned_from_local) = assigned_from.local_or_deref_local()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if assigned_from_local != target {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a closure captured our `target` and then assigned
|
||||
// into a place then we should annotate the closure in
|
||||
// case it ends up being assigned into the return place.
|
||||
annotated_closure =
|
||||
self.annotate_fn_sig(def_id, args.as_closure().sig());
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
annotated_closure={:?} assigned_from_local={:?} \
|
||||
assigned_to={:?}",
|
||||
annotated_closure, assigned_from_local, assigned_to
|
||||
);
|
||||
|
||||
if assigned_to == mir::RETURN_PLACE {
|
||||
// If it was assigned directly into the return place, then
|
||||
// return now.
|
||||
return annotated_closure;
|
||||
} else {
|
||||
// Otherwise, update the target.
|
||||
target = assigned_to;
|
||||
}
|
||||
if assigned_from_local != target {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If none of our closure's operands matched, then skip to the next
|
||||
// statement.
|
||||
continue;
|
||||
// If a closure captured our `target` and then assigned
|
||||
// into a place then we should annotate the closure in
|
||||
// case it ends up being assigned into the return place.
|
||||
annotated_closure =
|
||||
self.annotate_fn_sig(def_id, args.as_closure().sig());
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
annotated_closure={:?} assigned_from_local={:?} \
|
||||
assigned_to={:?}",
|
||||
annotated_closure, assigned_from_local, assigned_to
|
||||
);
|
||||
|
||||
if assigned_to == mir::RETURN_PLACE {
|
||||
// If it was assigned directly into the return place, then
|
||||
// return now.
|
||||
return annotated_closure;
|
||||
} else {
|
||||
// Otherwise, update the target.
|
||||
target = assigned_to;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, look at other types of assignment.
|
||||
let assigned_from = match rvalue {
|
||||
Rvalue::Ref(_, _, assigned_from) => assigned_from,
|
||||
Rvalue::Use(operand) => match operand {
|
||||
Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
|
||||
assigned_from
|
||||
}
|
||||
_ => continue,
|
||||
},
|
||||
_ => continue,
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from={:?}",
|
||||
assigned_from,
|
||||
);
|
||||
|
||||
// Find the local from the rvalue.
|
||||
let Some(assigned_from_local) = assigned_from.local_or_deref_local() else {
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from_local={:?}",
|
||||
assigned_from_local,
|
||||
);
|
||||
|
||||
// Check if our local matches the target - if so, we've assigned our
|
||||
// borrow to a new place.
|
||||
if assigned_from_local != target {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we assigned our `target` into a new place, then we should
|
||||
// check if it was the return place.
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from_local={:?} assigned_to={:?}",
|
||||
assigned_from_local, assigned_to
|
||||
);
|
||||
if assigned_to == mir::RETURN_PLACE {
|
||||
// If it was then return the annotated closure if there was one,
|
||||
// else, annotate this function.
|
||||
return annotated_closure.or_else(fallback);
|
||||
}
|
||||
|
||||
// If we didn't assign into the return place, then we just update
|
||||
// the target.
|
||||
target = assigned_to;
|
||||
// If none of our closure's operands matched, then skip to the next
|
||||
// statement.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, look at other types of assignment.
|
||||
let assigned_from = match rvalue {
|
||||
Rvalue::Ref(_, _, assigned_from) => assigned_from,
|
||||
Rvalue::Use(operand) => match operand {
|
||||
Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
|
||||
assigned_from
|
||||
}
|
||||
_ => continue,
|
||||
},
|
||||
_ => continue,
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from={:?}",
|
||||
assigned_from,
|
||||
);
|
||||
|
||||
// Find the local from the rvalue.
|
||||
let Some(assigned_from_local) = assigned_from.local_or_deref_local() else {
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from_local={:?}",
|
||||
assigned_from_local,
|
||||
);
|
||||
|
||||
// Check if our local matches the target - if so, we've assigned our
|
||||
// borrow to a new place.
|
||||
if assigned_from_local != target {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we assigned our `target` into a new place, then we should
|
||||
// check if it was the return place.
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: \
|
||||
assigned_from_local={:?} assigned_to={:?}",
|
||||
assigned_from_local, assigned_to
|
||||
);
|
||||
if assigned_to == mir::RETURN_PLACE {
|
||||
// If it was then return the annotated closure if there was one,
|
||||
// else, annotate this function.
|
||||
return annotated_closure.or_else(fallback);
|
||||
}
|
||||
|
||||
// If we didn't assign into the return place, then we just update
|
||||
// the target.
|
||||
target = assigned_to;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4172,32 +4168,31 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
);
|
||||
if let TerminatorKind::Call { destination, target: Some(_), args, .. } =
|
||||
&terminator.kind
|
||||
&& let Some(assigned_to) = destination.as_local()
|
||||
{
|
||||
if let Some(assigned_to) = destination.as_local() {
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
|
||||
assigned_to, args
|
||||
);
|
||||
for operand in args {
|
||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
|
||||
&operand.node
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
|
||||
assigned_to, args
|
||||
"annotate_argument_and_return_for_borrow: assigned_from={:?}",
|
||||
assigned_from,
|
||||
);
|
||||
for operand in args {
|
||||
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
|
||||
&operand.node
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_from={:?}",
|
||||
assigned_from,
|
||||
"annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
|
||||
assigned_from_local,
|
||||
);
|
||||
|
||||
if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
|
||||
assigned_from_local,
|
||||
);
|
||||
|
||||
if assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
|
||||
return annotated_closure.or_else(fallback);
|
||||
}
|
||||
if assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
|
||||
return annotated_closure.or_else(fallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4296,10 +4291,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
// as the HIR doesn't have full types for closure arguments.
|
||||
let return_ty = sig.output().skip_binder();
|
||||
let mut return_span = fn_decl.output.span();
|
||||
if let hir::FnRetTy::Return(ty) = &fn_decl.output {
|
||||
if let hir::TyKind::Ref(lifetime, _) = ty.kind {
|
||||
return_span = lifetime.ident.span;
|
||||
}
|
||||
if let hir::FnRetTy::Return(ty) = &fn_decl.output
|
||||
&& let hir::TyKind::Ref(lifetime, _) = ty.kind
|
||||
{
|
||||
return_span = lifetime.ident.span;
|
||||
}
|
||||
|
||||
Some(AnnotatedBorrowFnSignature::NamedFunction {
|
||||
|
|
|
|||
|
|
@ -917,30 +917,29 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
|
||||
if let TerminatorKind::Call { destination, target: Some(block), args, .. } =
|
||||
&terminator.kind
|
||||
&& let Some(dest) = destination.as_local()
|
||||
{
|
||||
if let Some(dest) = destination.as_local() {
|
||||
debug!(
|
||||
"was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
|
||||
target, dest, args
|
||||
);
|
||||
// Check if one of the arguments to this function is the target place.
|
||||
let found_target = args.iter().any(|arg| {
|
||||
if let Operand::Move(place) = arg.node {
|
||||
if let Some(potential) = place.as_local() {
|
||||
potential == target
|
||||
} else {
|
||||
false
|
||||
}
|
||||
debug!(
|
||||
"was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
|
||||
target, dest, args
|
||||
);
|
||||
// Check if one of the arguments to this function is the target place.
|
||||
let found_target = args.iter().any(|arg| {
|
||||
if let Operand::Move(place) = arg.node {
|
||||
if let Some(potential) = place.as_local() {
|
||||
potential == target
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// If it is, follow this to the next block and update the target.
|
||||
if found_target {
|
||||
target = dest;
|
||||
queue.push(block.start_location());
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// If it is, follow this to the next block and update the target.
|
||||
if found_target {
|
||||
target = dest;
|
||||
queue.push(block.start_location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,48 +266,44 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
args,
|
||||
..
|
||||
} = &terminator.kind
|
||||
&& let ty::FnDef(id, _) = *const_.ty().kind()
|
||||
{
|
||||
if let ty::FnDef(id, _) = *const_.ty().kind() {
|
||||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||
if self.infcx.tcx.is_lang_item(self.infcx.tcx.parent(id), LangItem::FnOnce) {
|
||||
let closure = match args.first() {
|
||||
Some(Spanned {
|
||||
node: Operand::Copy(place) | Operand::Move(place), ..
|
||||
}) if target == place.local_or_deref_local() => {
|
||||
place.local_or_deref_local().unwrap()
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||
if self.infcx.tcx.is_lang_item(self.infcx.tcx.parent(id), LangItem::FnOnce) {
|
||||
let closure = match args.first() {
|
||||
Some(Spanned { node: Operand::Copy(place) | Operand::Move(place), .. })
|
||||
if target == place.local_or_deref_local() =>
|
||||
{
|
||||
place.local_or_deref_local().unwrap()
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
|
||||
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.subdiagnostic(OnClosureNote::InvokedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(
|
||||
self.infcx.tcx,
|
||||
hir_place,
|
||||
),
|
||||
span: *span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
|
||||
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.subdiagnostic(OnClosureNote::InvokedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we are just moving a closure after it has been invoked.
|
||||
if let Some(target) = target {
|
||||
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.subdiagnostic(OnClosureNote::MovedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if let Some(target) = target
|
||||
&& let ty::Closure(did, _) = self.body.local_decls[target].ty.kind()
|
||||
{
|
||||
let did = did.expect_local();
|
||||
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
|
||||
diag.subdiagnostic(OnClosureNote::MovedTwice {
|
||||
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
|
||||
span: *span,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
|
|
|
|||
|
|
@ -126,36 +126,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
.statements
|
||||
.get(location.statement_index)
|
||||
.map(|stmt| &stmt.kind)
|
||||
&& let Some(local) = place.as_local()
|
||||
{
|
||||
if let Some(local) = place.as_local() {
|
||||
let local_decl = &self.body.local_decls[local];
|
||||
// opt_match_place is the
|
||||
// match_span is the span of the expression being matched on
|
||||
// match *x.y { ... } match_place is Some(*x.y)
|
||||
// ^^^^ match_span is the span of *x.y
|
||||
//
|
||||
// opt_match_place is None for let [mut] x = ... statements,
|
||||
// whether or not the right-hand side is a place expression
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
})) = *local_decl.local_info()
|
||||
{
|
||||
let stmt_source_info = self.body.source_info(location);
|
||||
self.append_binding_error(
|
||||
grouped_errors,
|
||||
kind,
|
||||
original_path,
|
||||
*move_from,
|
||||
local,
|
||||
opt_match_place,
|
||||
match_span,
|
||||
stmt_source_info.span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
let local_decl = &self.body.local_decls[local];
|
||||
// opt_match_place is the
|
||||
// match_span is the span of the expression being matched on
|
||||
// match *x.y { ... } match_place is Some(*x.y)
|
||||
// ^^^^ match_span is the span of *x.y
|
||||
//
|
||||
// opt_match_place is None for let [mut] x = ... statements,
|
||||
// whether or not the right-hand side is a place expression
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
})) = *local_decl.local_info()
|
||||
{
|
||||
let stmt_source_info = self.body.source_info(location);
|
||||
self.append_binding_error(
|
||||
grouped_errors,
|
||||
kind,
|
||||
original_path,
|
||||
*move_from,
|
||||
local,
|
||||
opt_match_place,
|
||||
match_span,
|
||||
stmt_source_info.span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -528,15 +528,15 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
// match_adt_and_segment in this case.
|
||||
Res::Def(DefKind::TyAlias, _) => (),
|
||||
_ => {
|
||||
if let Some(last_segment) = path.segments.last() {
|
||||
if let Some(highlight) = self.match_adt_and_segment(
|
||||
if let Some(last_segment) = path.segments.last()
|
||||
&& let Some(highlight) = self.match_adt_and_segment(
|
||||
args,
|
||||
needle_fr,
|
||||
last_segment,
|
||||
search_stack,
|
||||
) {
|
||||
return Some(highlight);
|
||||
}
|
||||
)
|
||||
{
|
||||
return Some(highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -822,10 +822,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements {
|
||||
if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) {
|
||||
continue;
|
||||
}
|
||||
if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements
|
||||
&& self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Type-test failed. Report the error.
|
||||
|
|
@ -1479,40 +1479,36 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
shorter_fr: RegionVid,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
) -> RegionRelationCheckResult {
|
||||
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
|
||||
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements
|
||||
// Shrink `longer_fr` until we find a non-local region (if we do).
|
||||
// We'll call it `fr-` -- it's ever so slightly smaller than
|
||||
// `longer_fr`.
|
||||
if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
|
||||
{
|
||||
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
|
||||
&& let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
|
||||
{
|
||||
debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
|
||||
|
||||
let blame_span_category = self.find_outlives_blame_span(
|
||||
longer_fr,
|
||||
NllRegionVariableOrigin::FreeRegion,
|
||||
shorter_fr,
|
||||
);
|
||||
let blame_span_category = self.find_outlives_blame_span(
|
||||
longer_fr,
|
||||
NllRegionVariableOrigin::FreeRegion,
|
||||
shorter_fr,
|
||||
);
|
||||
|
||||
// Grow `shorter_fr` until we find some non-local regions. (We
|
||||
// always will.) We'll call them `shorter_fr+` -- they're ever
|
||||
// so slightly larger than `shorter_fr`.
|
||||
let shorter_fr_plus =
|
||||
self.universal_region_relations.non_local_upper_bounds(shorter_fr);
|
||||
debug!(
|
||||
"try_propagate_universal_region_error: shorter_fr_plus={:?}",
|
||||
shorter_fr_plus
|
||||
);
|
||||
for fr in shorter_fr_plus {
|
||||
// Push the constraint `fr-: shorter_fr+`
|
||||
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
||||
subject: ClosureOutlivesSubject::Region(fr_minus),
|
||||
outlived_free_region: fr,
|
||||
blame_span: blame_span_category.1.span,
|
||||
category: blame_span_category.0,
|
||||
});
|
||||
}
|
||||
return RegionRelationCheckResult::Propagated;
|
||||
// Grow `shorter_fr` until we find some non-local regions. (We
|
||||
// always will.) We'll call them `shorter_fr+` -- they're ever
|
||||
// so slightly larger than `shorter_fr`.
|
||||
let shorter_fr_plus =
|
||||
self.universal_region_relations.non_local_upper_bounds(shorter_fr);
|
||||
debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus);
|
||||
for fr in shorter_fr_plus {
|
||||
// Push the constraint `fr-: shorter_fr+`
|
||||
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
||||
subject: ClosureOutlivesSubject::Region(fr_minus),
|
||||
outlived_free_region: fr,
|
||||
blame_span: blame_span_category.1.span,
|
||||
category: blame_span_category.0,
|
||||
});
|
||||
}
|
||||
return RegionRelationCheckResult::Propagated;
|
||||
}
|
||||
|
||||
RegionRelationCheckResult::Error
|
||||
|
|
@ -2085,11 +2081,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let locations = self.scc_values.locations_outlived_by(scc);
|
||||
for location in locations {
|
||||
let bb = &body[location.block];
|
||||
if let Some(terminator) = &bb.terminator {
|
||||
if let Some(terminator) = &bb.terminator
|
||||
// terminator of a loop should be TerminatorKind::FalseUnwind
|
||||
if let TerminatorKind::FalseUnwind { .. } = terminator.kind {
|
||||
return Some(location);
|
||||
}
|
||||
&& let TerminatorKind::FalseUnwind { .. } = terminator.kind
|
||||
{
|
||||
return Some(location);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -669,24 +669,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(annotation_index) = self.rvalue_user_ty(rv) {
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
if let Some(annotation_index) = self.rvalue_user_ty(rv)
|
||||
&& let Err(terr) = self.relate_type_and_user_type(
|
||||
rv_ty,
|
||||
ty::Invariant,
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
|
||||
) {
|
||||
let annotation = &self.user_type_annotations[annotation_index];
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
"bad user type on rvalue ({:?} = {:?}): {:?}",
|
||||
annotation,
|
||||
rv_ty,
|
||||
terr
|
||||
);
|
||||
}
|
||||
)
|
||||
{
|
||||
let annotation = &self.user_type_annotations[annotation_index];
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
"bad user type on rvalue ({:?} = {:?}): {:?}",
|
||||
annotation,
|
||||
rv_ty,
|
||||
terr
|
||||
);
|
||||
}
|
||||
|
||||
if !self.unsized_feature_enabled() {
|
||||
|
|
|
|||
|
|
@ -505,10 +505,10 @@ fn thin_lto(
|
|||
|
||||
// Save the current ThinLTO import information for the next compilation
|
||||
// session, overwriting the previous serialized data (if any).
|
||||
if let Some(path) = key_map_path {
|
||||
if let Err(err) = curr_key_map.save_to_file(&path) {
|
||||
return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }));
|
||||
}
|
||||
if let Some(path) = key_map_path
|
||||
&& let Err(err) = curr_key_map.save_to_file(&path)
|
||||
{
|
||||
return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }));
|
||||
}
|
||||
|
||||
Ok((opt_jobs, copy_jobs))
|
||||
|
|
|
|||
|
|
@ -687,10 +687,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
bx.nonnull_metadata(load);
|
||||
}
|
||||
|
||||
if let Some(pointee) = layout.pointee_info_at(bx, offset) {
|
||||
if let Some(_) = pointee.safe {
|
||||
bx.align_metadata(load, pointee.align);
|
||||
}
|
||||
if let Some(pointee) = layout.pointee_info_at(bx, offset)
|
||||
&& let Some(_) = pointee.safe
|
||||
{
|
||||
bx.align_metadata(load, pointee.align);
|
||||
}
|
||||
}
|
||||
abi::Primitive::Float(_) => {}
|
||||
|
|
|
|||
|
|
@ -3369,12 +3369,12 @@ fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn s
|
|||
|
||||
let section =
|
||||
elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
|
||||
if let Some((_, section)) = section {
|
||||
if let Some(mut notes) = section.notes(endian, data)? {
|
||||
return Ok(notes.any(|note| {
|
||||
note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
|
||||
}));
|
||||
}
|
||||
if let Some((_, section)) = section
|
||||
&& let Some(mut notes) = section.notes(endian, data)?
|
||||
{
|
||||
return Ok(notes.any(|note| {
|
||||
note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
|
|
|
|||
|
|
@ -496,17 +496,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
)
|
||||
.with_note("Rustc requires this item to have a specific mangled name.")
|
||||
.with_span_label(tcx.def_span(did), "should be the internal language item");
|
||||
if let Some(lang_item) = lang_item {
|
||||
if let Some(link_name) = lang_item.link_name() {
|
||||
err = err
|
||||
.with_note("If you are trying to prevent mangling to ease debugging, many")
|
||||
.with_note(format!(
|
||||
"debuggers support a command such as `rbreak {link_name}` to"
|
||||
))
|
||||
.with_note(format!(
|
||||
"match `.*{link_name}.*` instead of `break {link_name}` on a specific name"
|
||||
))
|
||||
}
|
||||
if let Some(lang_item) = lang_item
|
||||
&& let Some(link_name) = lang_item.link_name()
|
||||
{
|
||||
err = err
|
||||
.with_note("If you are trying to prevent mangling to ease debugging, many")
|
||||
.with_note(format!("debuggers support a command such as `rbreak {link_name}` to"))
|
||||
.with_note(format!(
|
||||
"match `.*{link_name}.*` instead of `break {link_name}` on a specific name"
|
||||
))
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -714,10 +714,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
|
||||
self.super_operand(op, location);
|
||||
if let Operand::Constant(c) = op {
|
||||
if let Some(def_id) = c.check_static_ptr(self.tcx) {
|
||||
self.check_static(def_id, self.span);
|
||||
}
|
||||
if let Operand::Constant(c) = op
|
||||
&& let Some(def_id) = c.check_static_ptr(self.tcx)
|
||||
{
|
||||
self.check_static(def_id, self.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,21 +295,18 @@ fn build_error_for_const_call<'tcx>(
|
|||
}
|
||||
let deref = "*".repeat(num_refs);
|
||||
|
||||
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
|
||||
if let Some(eq_idx) = call_str.find("==") {
|
||||
if let Some(rhs_idx) =
|
||||
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
|
||||
{
|
||||
let rhs_pos =
|
||||
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
|
||||
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
|
||||
sugg = Some(errors::ConsiderDereferencing {
|
||||
deref,
|
||||
span: span.shrink_to_lo(),
|
||||
rhs_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span)
|
||||
&& let Some(eq_idx) = call_str.find("==")
|
||||
&& let Some(rhs_idx) =
|
||||
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
|
||||
{
|
||||
let rhs_pos = span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
|
||||
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
|
||||
sugg = Some(errors::ConsiderDereferencing {
|
||||
deref,
|
||||
span: span.shrink_to_lo(),
|
||||
rhs_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -137,14 +137,14 @@ where
|
|||
|
||||
// If a local with no projections is moved from (e.g. `x` in `y = x`), record that
|
||||
// it no longer needs to be dropped.
|
||||
if let mir::Operand::Move(place) = operand {
|
||||
if let Some(local) = place.as_local() {
|
||||
// For backward compatibility with the MaybeMutBorrowedLocals used in an earlier
|
||||
// implementation we retain qualif if a local had been borrowed before. This might
|
||||
// not be strictly necessary since the local is no longer initialized.
|
||||
if !self.state.borrow.contains(local) {
|
||||
self.state.qualif.remove(local);
|
||||
}
|
||||
if let mir::Operand::Move(place) = operand
|
||||
&& let Some(local) = place.as_local()
|
||||
{
|
||||
// For backward compatibility with the MaybeMutBorrowedLocals used in an earlier
|
||||
// implementation we retain qualif if a local had been borrowed before. This might
|
||||
// not be strictly necessary since the local is no longer initialized.
|
||||
if !self.state.borrow.contains(local) {
|
||||
self.state.qualif.remove(local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -442,10 +442,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// # First compute the dynamic alignment
|
||||
|
||||
// Packed type alignment needs to be capped.
|
||||
if let ty::Adt(def, _) = layout.ty.kind() {
|
||||
if let Some(packed) = def.repr().pack {
|
||||
unsized_align = unsized_align.min(packed);
|
||||
}
|
||||
if let ty::Adt(def, _) = layout.ty.kind()
|
||||
&& let Some(packed) = def.repr().pack
|
||||
{
|
||||
unsized_align = unsized_align.min(packed);
|
||||
}
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
|
|
|
|||
|
|
@ -320,10 +320,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
// for a coroutine).
|
||||
let var_hir_id = captured_place.get_root_variable();
|
||||
let node = self.ecx.tcx.hir_node(var_hir_id);
|
||||
if let hir::Node::Pat(pat) = node {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
|
||||
name = Some(ident.name);
|
||||
}
|
||||
if let hir::Node::Pat(pat) = node
|
||||
&& let hir::PatKind::Binding(_, _, ident, _) = pat.kind
|
||||
{
|
||||
name = Some(ident.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,12 +153,11 @@ impl StyledBuffer {
|
|||
/// 1. That line and column exist in `StyledBuffer`
|
||||
/// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation`
|
||||
fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
|
||||
if let Some(ref mut line) = self.lines.get_mut(line) {
|
||||
if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
|
||||
if overwrite || matches!(s, Style::NoStyle | Style::Quotation) {
|
||||
*s = style;
|
||||
}
|
||||
}
|
||||
if let Some(ref mut line) = self.lines.get_mut(line)
|
||||
&& let Some(StyledChar { style: s, .. }) = line.get_mut(col)
|
||||
&& (overwrite || matches!(s, Style::NoStyle | Style::Quotation))
|
||||
{
|
||||
*s = style;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -530,13 +530,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, a)| {
|
||||
if let hir::TyKind::Infer(()) = a.kind {
|
||||
if let Some(suggested_ty) =
|
||||
if let hir::TyKind::Infer(()) = a.kind
|
||||
&& let Some(suggested_ty) =
|
||||
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
|
||||
{
|
||||
infer_replacements.push((a.span, suggested_ty.to_string()));
|
||||
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
|
||||
}
|
||||
{
|
||||
infer_replacements.push((a.span, suggested_ty.to_string()));
|
||||
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
|
||||
}
|
||||
|
||||
self.lowerer().lower_ty(a)
|
||||
|
|
|
|||
|
|
@ -617,18 +617,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
});
|
||||
|
||||
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
|
||||
if let Some(const_arg) = constraint.ct() {
|
||||
if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
|
||||
let ty = alias_term
|
||||
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
||||
let ty = check_assoc_const_binding_type(
|
||||
self,
|
||||
constraint.ident,
|
||||
ty,
|
||||
constraint.hir_id,
|
||||
);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
if let Some(const_arg) = constraint.ct()
|
||||
&& let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
|
||||
{
|
||||
let ty = alias_term
|
||||
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
||||
let ty =
|
||||
check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
|
||||
alias_term
|
||||
|
|
|
|||
|
|
@ -103,16 +103,15 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
|||
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
|
||||
if self.depth >= self.cause_depth {
|
||||
self.cause = Some(error.obligation.cause);
|
||||
if let hir::TyKind::TraitObject(..) = ty.kind {
|
||||
if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn =
|
||||
if let hir::TyKind::TraitObject(..) = ty.kind
|
||||
&& let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn =
|
||||
self.tcx.def_kind(self.def_id)
|
||||
{
|
||||
self.cause = Some(ObligationCause::new(
|
||||
ty.span,
|
||||
self.def_id,
|
||||
ObligationCauseCode::DynCompatible(ty.span),
|
||||
));
|
||||
}
|
||||
{
|
||||
self.cause = Some(ObligationCause::new(
|
||||
ty.span,
|
||||
self.def_id,
|
||||
ObligationCauseCode::DynCompatible(ty.span),
|
||||
));
|
||||
}
|
||||
self.cause_depth = self.depth
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2136,10 +2136,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
)
|
||||
};
|
||||
|
||||
if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
|
||||
if let Some(rslt) = check_in_progress(el) {
|
||||
return rslt;
|
||||
}
|
||||
if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
|
||||
&& let Some(rslt) = check_in_progress(el)
|
||||
{
|
||||
return rslt;
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Match(_, arms, _) = expr.kind {
|
||||
|
|
|
|||
|
|
@ -615,31 +615,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) -> bool {
|
||||
if let (ty::FnPtr(..), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
|
||||
if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
|
||||
// Report upto four upvars being captured to reduce the amount error messages
|
||||
// reported back to the user.
|
||||
let spans_and_labels = upvars
|
||||
.iter()
|
||||
.take(4)
|
||||
.map(|(var_hir_id, upvar)| {
|
||||
let var_name = self.tcx.hir_name(*var_hir_id).to_string();
|
||||
let msg = format!("`{var_name}` captured here");
|
||||
(upvar.span, msg)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if let (ty::FnPtr(..), ty::Closure(def_id, _)) = (expected.kind(), found.kind())
|
||||
&& let Some(upvars) = self.tcx.upvars_mentioned(*def_id)
|
||||
{
|
||||
// Report upto four upvars being captured to reduce the amount error messages
|
||||
// reported back to the user.
|
||||
let spans_and_labels = upvars
|
||||
.iter()
|
||||
.take(4)
|
||||
.map(|(var_hir_id, upvar)| {
|
||||
let var_name = self.tcx.hir_name(*var_hir_id).to_string();
|
||||
let msg = format!("`{var_name}` captured here");
|
||||
(upvar.span, msg)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut multi_span: MultiSpan =
|
||||
spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().into();
|
||||
for (sp, label) in spans_and_labels {
|
||||
multi_span.push_span_label(sp, label);
|
||||
}
|
||||
err.span_note(
|
||||
multi_span,
|
||||
"closures can only be coerced to `fn` types if they do not capture any variables"
|
||||
);
|
||||
return true;
|
||||
let mut multi_span: MultiSpan =
|
||||
spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().into();
|
||||
for (sp, label) in spans_and_labels {
|
||||
multi_span.push_span_label(sp, label);
|
||||
}
|
||||
err.span_note(
|
||||
multi_span,
|
||||
"closures can only be coerced to `fn` types if they do not capture any variables",
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -3008,13 +3008,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// Returns whether the given expression is an `else if`.
|
||||
fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
if let hir::ExprKind::If(..) = expr.kind {
|
||||
if let Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::If(_, _, Some(else_expr)), ..
|
||||
}) = self.tcx.parent_hir_node(expr.hir_id)
|
||||
{
|
||||
return else_expr.hir_id == expr.hir_id;
|
||||
}
|
||||
if let hir::ExprKind::If(..) = expr.kind
|
||||
&& let Node::Expr(hir::Expr { kind: hir::ExprKind::If(_, _, Some(else_expr)), .. }) =
|
||||
self.tcx.parent_hir_node(expr.hir_id)
|
||||
{
|
||||
return else_expr.hir_id == expr.hir_id;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,17 +669,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
|
||||
fn check_for_illegal_method_calls(&self, pick: &probe::Pick<'_>) {
|
||||
// Disallow calls to the method `drop` defined in the `Drop` trait.
|
||||
if let Some(trait_def_id) = pick.item.trait_container(self.tcx) {
|
||||
if let Err(e) = callee::check_legal_trait_for_method_call(
|
||||
if let Some(trait_def_id) = pick.item.trait_container(self.tcx)
|
||||
&& let Err(e) = callee::check_legal_trait_for_method_call(
|
||||
self.tcx,
|
||||
self.span,
|
||||
Some(self.self_expr.span),
|
||||
self.call_expr.span,
|
||||
trait_def_id,
|
||||
self.body_id.to_def_id(),
|
||||
) {
|
||||
self.set_tainted_by_errors(e);
|
||||
}
|
||||
)
|
||||
{
|
||||
self.set_tainted_by_errors(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,13 +165,12 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
|
|||
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) =
|
||||
obligation.predicate.kind().skip_binder()
|
||||
{
|
||||
// If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
|
||||
// we need to make it into one.
|
||||
if let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid()) {
|
||||
debug!("infer_var_info: {:?}.output = true", vid);
|
||||
infer_var_info.entry(vid).or_default().output = true;
|
||||
}
|
||||
&& let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid())
|
||||
{
|
||||
debug!("infer_var_info: {:?}.output = true", vid);
|
||||
infer_var_info.entry(vid).or_default().output = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,21 +227,19 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||
self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
|
||||
self.typeck_results.node_args_mut().remove(e.hir_id);
|
||||
|
||||
if let Some(a) = self.typeck_results.adjustments_mut().get_mut(base.hir_id) {
|
||||
if let Some(a) = self.typeck_results.adjustments_mut().get_mut(base.hir_id)
|
||||
// Discard the need for a mutable borrow
|
||||
|
||||
// Extra adjustment made when indexing causes a drop
|
||||
// of size information - we need to get rid of it
|
||||
// Since this is "after" the other adjustment to be
|
||||
// discarded, we do an extra `pop()`
|
||||
if let Some(Adjustment {
|
||||
&& let Some(Adjustment {
|
||||
kind: Adjust::Pointer(PointerCoercion::Unsize),
|
||||
..
|
||||
}) = a.pop()
|
||||
{
|
||||
// So the borrow discard actually happens here
|
||||
a.pop();
|
||||
}
|
||||
{
|
||||
// So the borrow discard actually happens here
|
||||
a.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2446,16 +2446,16 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
|
||||
/// Determine if this expression is a "dangerous initialization".
|
||||
fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitKind> {
|
||||
if let hir::ExprKind::Call(path_expr, args) = expr.kind {
|
||||
if let hir::ExprKind::Call(path_expr, args) = expr.kind
|
||||
// Find calls to `mem::{uninitialized,zeroed}` methods.
|
||||
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
||||
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||
match cx.tcx.get_diagnostic_name(def_id) {
|
||||
Some(sym::mem_zeroed) => return Some(InitKind::Zeroed),
|
||||
Some(sym::mem_uninitialized) => return Some(InitKind::Uninit),
|
||||
Some(sym::transmute) if is_zero(&args[0]) => return Some(InitKind::Zeroed),
|
||||
_ => {}
|
||||
}
|
||||
&& let hir::ExprKind::Path(ref qpath) = path_expr.kind
|
||||
{
|
||||
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||
match cx.tcx.get_diagnostic_name(def_id) {
|
||||
Some(sym::mem_zeroed) => return Some(InitKind::Zeroed),
|
||||
Some(sym::mem_uninitialized) => return Some(InitKind::Uninit),
|
||||
Some(sym::transmute) if is_zero(&args[0]) => return Some(InitKind::Zeroed),
|
||||
_ => {}
|
||||
}
|
||||
} else if let hir::ExprKind::MethodCall(_, receiver, ..) = expr.kind {
|
||||
// Find problematic calls to `MaybeUninit::assume_init`.
|
||||
|
|
@ -2463,14 +2463,14 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
|
||||
// This is a call to *some* method named `assume_init`.
|
||||
// See if the `self` parameter is one of the dangerous constructors.
|
||||
if let hir::ExprKind::Call(path_expr, _) = receiver.kind {
|
||||
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
||||
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||
match cx.tcx.get_diagnostic_name(def_id) {
|
||||
Some(sym::maybe_uninit_zeroed) => return Some(InitKind::Zeroed),
|
||||
Some(sym::maybe_uninit_uninit) => return Some(InitKind::Uninit),
|
||||
_ => {}
|
||||
}
|
||||
if let hir::ExprKind::Call(path_expr, _) = receiver.kind
|
||||
&& let hir::ExprKind::Path(ref qpath) = path_expr.kind
|
||||
{
|
||||
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
|
||||
match cx.tcx.get_diagnostic_name(def_id) {
|
||||
Some(sym::maybe_uninit_zeroed) => return Some(InitKind::Zeroed),
|
||||
Some(sym::maybe_uninit_uninit) => return Some(InitKind::Uninit),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2724,13 +2724,13 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
|
|||
}
|
||||
// check for call to `core::ptr::null` or `core::ptr::null_mut`
|
||||
hir::ExprKind::Call(path, _) => {
|
||||
if let hir::ExprKind::Path(ref qpath) = path.kind {
|
||||
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() {
|
||||
return matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_null | sym::ptr_null_mut)
|
||||
);
|
||||
}
|
||||
if let hir::ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
{
|
||||
return matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_null | sym::ptr_null_mut)
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -411,22 +411,21 @@ declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
|
|||
|
||||
impl EarlyLintPass for LintPassImpl {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind {
|
||||
if let Some(last) = lint_pass.path.segments.last() {
|
||||
if last.ident.name == sym::LintPass {
|
||||
let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
|
||||
let call_site = expn_data.call_site;
|
||||
if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
|
||||
&& call_site.ctxt().outer_expn_data().kind
|
||||
!= ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||
lint_pass.path.span,
|
||||
LintPassByHand,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind
|
||||
&& let Some(last) = lint_pass.path.segments.last()
|
||||
&& last.ident.name == sym::LintPass
|
||||
{
|
||||
let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
|
||||
let call_site = expn_data.call_site;
|
||||
if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
|
||||
&& call_site.ctxt().outer_expn_data().kind
|
||||
!= ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||
lint_pass.path.span,
|
||||
LintPassByHand,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,56 +43,50 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
|
|||
return;
|
||||
}
|
||||
|
||||
if let StmtKind::Semi(expr) = stmt.kind {
|
||||
if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind {
|
||||
if path.ident.name.as_str() == "map" {
|
||||
if receiver.span.from_expansion()
|
||||
|| args.iter().any(|e| e.span.from_expansion())
|
||||
|| !is_impl_slice(cx, receiver)
|
||||
|| !is_diagnostic_name(cx, expr.hir_id, "IteratorMap")
|
||||
{
|
||||
return;
|
||||
if let StmtKind::Semi(expr) = stmt.kind
|
||||
&& let ExprKind::MethodCall(path, receiver, args, span) = expr.kind
|
||||
{
|
||||
if path.ident.name.as_str() == "map" {
|
||||
if receiver.span.from_expansion()
|
||||
|| args.iter().any(|e| e.span.from_expansion())
|
||||
|| !is_impl_slice(cx, receiver)
|
||||
|| !is_diagnostic_name(cx, expr.hir_id, "IteratorMap")
|
||||
{
|
||||
return;
|
||||
}
|
||||
let arg_ty = cx.typeck_results().expr_ty(&args[0]);
|
||||
let default_span = args[0].span;
|
||||
if let ty::FnDef(id, _) = arg_ty.kind() {
|
||||
let fn_ty = cx.tcx.fn_sig(id).skip_binder();
|
||||
let ret_ty = fn_ty.output().skip_binder();
|
||||
if is_unit_type(ret_ty) {
|
||||
cx.emit_span_lint(
|
||||
MAP_UNIT_FN,
|
||||
span,
|
||||
MappingToUnit {
|
||||
function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span),
|
||||
argument_label: args[0].span,
|
||||
map_label: span,
|
||||
suggestion: path.ident.span,
|
||||
replace: "for_each".to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
let arg_ty = cx.typeck_results().expr_ty(&args[0]);
|
||||
let default_span = args[0].span;
|
||||
if let ty::FnDef(id, _) = arg_ty.kind() {
|
||||
let fn_ty = cx.tcx.fn_sig(id).skip_binder();
|
||||
let ret_ty = fn_ty.output().skip_binder();
|
||||
if is_unit_type(ret_ty) {
|
||||
cx.emit_span_lint(
|
||||
MAP_UNIT_FN,
|
||||
span,
|
||||
MappingToUnit {
|
||||
function_label: cx
|
||||
.tcx
|
||||
.span_of_impl(*id)
|
||||
.unwrap_or(default_span),
|
||||
argument_label: args[0].span,
|
||||
map_label: span,
|
||||
suggestion: path.ident.span,
|
||||
replace: "for_each".to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
} else if let ty::Closure(id, subs) = arg_ty.kind() {
|
||||
let cl_ty = subs.as_closure().sig();
|
||||
let ret_ty = cl_ty.output().skip_binder();
|
||||
if is_unit_type(ret_ty) {
|
||||
cx.emit_span_lint(
|
||||
MAP_UNIT_FN,
|
||||
span,
|
||||
MappingToUnit {
|
||||
function_label: cx
|
||||
.tcx
|
||||
.span_of_impl(*id)
|
||||
.unwrap_or(default_span),
|
||||
argument_label: args[0].span,
|
||||
map_label: span,
|
||||
suggestion: path.ident.span,
|
||||
replace: "for_each".to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
} else if let ty::Closure(id, subs) = arg_ty.kind() {
|
||||
let cl_ty = subs.as_closure().sig();
|
||||
let ret_ty = cl_ty.output().skip_binder();
|
||||
if is_unit_type(ret_ty) {
|
||||
cx.emit_span_lint(
|
||||
MAP_UNIT_FN,
|
||||
span,
|
||||
MappingToUnit {
|
||||
function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span),
|
||||
argument_label: args[0].span,
|
||||
map_label: span,
|
||||
suggestion: path.ident.span,
|
||||
replace: "for_each".to_string(),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -101,10 +95,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
|
|||
}
|
||||
|
||||
fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(method_id) {
|
||||
return cx.tcx.type_of(impl_id).skip_binder().is_slice();
|
||||
}
|
||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
|
||||
{
|
||||
return cx.tcx.type_of(impl_id).skip_binder().is_slice();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -114,11 +108,11 @@ fn is_unit_type(ty: Ty<'_>) -> bool {
|
|||
}
|
||||
|
||||
fn is_diagnostic_name(cx: &LateContext<'_>, id: HirId, name: &str) -> bool {
|
||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id) {
|
||||
if let Some(item) = cx.tcx.get_diagnostic_name(def_id) {
|
||||
if item.as_str() == name {
|
||||
return true;
|
||||
}
|
||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id)
|
||||
&& let Some(item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
{
|
||||
if item.as_str() == name {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
|
|
|
|||
|
|
@ -48,38 +48,38 @@ declare_lint_pass!(NonPanicFmt => [NON_FMT_PANICS]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
|
||||
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
|
||||
let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
|
||||
if let hir::ExprKind::Call(f, [arg]) = &expr.kind
|
||||
&& let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind()
|
||||
{
|
||||
let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
|
||||
|
||||
if cx.tcx.is_lang_item(def_id, LangItem::BeginPanic)
|
||||
|| cx.tcx.is_lang_item(def_id, LangItem::Panic)
|
||||
|| f_diagnostic_name == Some(sym::panic_str_2015)
|
||||
if cx.tcx.is_lang_item(def_id, LangItem::BeginPanic)
|
||||
|| cx.tcx.is_lang_item(def_id, LangItem::Panic)
|
||||
|| f_diagnostic_name == Some(sym::panic_str_2015)
|
||||
{
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
if matches!(
|
||||
cx.tcx.get_diagnostic_name(id),
|
||||
Some(sym::core_panic_2015_macro | sym::std_panic_2015_macro)
|
||||
) {
|
||||
check_panic(cx, f, arg);
|
||||
}
|
||||
}
|
||||
} else if f_diagnostic_name == Some(sym::unreachable_display) {
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id
|
||||
&& cx.tcx.is_diagnostic_item(sym::unreachable_2015_macro, id)
|
||||
{
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
if matches!(
|
||||
cx.tcx.get_diagnostic_name(id),
|
||||
Some(sym::core_panic_2015_macro | sym::std_panic_2015_macro)
|
||||
) {
|
||||
check_panic(cx, f, arg);
|
||||
}
|
||||
}
|
||||
} else if f_diagnostic_name == Some(sym::unreachable_display) {
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
if cx.tcx.is_diagnostic_item(sym::unreachable_2015_macro, id) {
|
||||
check_panic(
|
||||
cx,
|
||||
f,
|
||||
// This is safe because we checked above that the callee is indeed
|
||||
// unreachable_display
|
||||
match &arg.kind {
|
||||
// Get the borrowed arg not the borrow
|
||||
hir::ExprKind::AddrOf(ast::BorrowKind::Ref, _, arg) => arg,
|
||||
_ => bug!("call to unreachable_display without borrow"),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
check_panic(
|
||||
cx,
|
||||
f,
|
||||
// This is safe because we checked above that the callee is indeed
|
||||
// unreachable_display
|
||||
match &arg.kind {
|
||||
// Get the borrowed arg not the borrow
|
||||
hir::ExprKind::AddrOf(ast::BorrowKind::Ref, _, arg) => arg,
|
||||
_ => bug!("call to unreachable_display without borrow"),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -623,15 +623,15 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
|
|||
..
|
||||
}) = p.kind
|
||||
{
|
||||
if let Res::Def(DefKind::Const, _) = path.res {
|
||||
if let [segment] = path.segments {
|
||||
NonUpperCaseGlobals::check_upper_case(
|
||||
cx,
|
||||
"constant in pattern",
|
||||
None,
|
||||
&segment.ident,
|
||||
);
|
||||
}
|
||||
if let Res::Def(DefKind::Const, _) = path.res
|
||||
&& let [segment] = path.segments
|
||||
{
|
||||
NonUpperCaseGlobals::check_upper_case(
|
||||
cx,
|
||||
"constant in pattern",
|
||||
None,
|
||||
&segment.ident,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -562,20 +562,19 @@ declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
||||
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
|
||||
if let hir::StmtKind::Semi(expr) = s.kind {
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if ty.needs_drop(cx.tcx, cx.typing_env()) {
|
||||
let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span)
|
||||
{
|
||||
PathStatementDropSub::Suggestion { span: s.span, snippet }
|
||||
} else {
|
||||
PathStatementDropSub::Help { span: s.span }
|
||||
};
|
||||
cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
|
||||
if let hir::StmtKind::Semi(expr) = s.kind
|
||||
&& let hir::ExprKind::Path(_) = expr.kind
|
||||
{
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if ty.needs_drop(cx.tcx, cx.typing_env()) {
|
||||
let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
|
||||
PathStatementDropSub::Suggestion { span: s.span, snippet }
|
||||
} else {
|
||||
cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
|
||||
}
|
||||
PathStatementDropSub::Help { span: s.span }
|
||||
};
|
||||
cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
|
||||
} else {
|
||||
cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1517,21 +1516,19 @@ impl UnusedDelimLint for UnusedBraces {
|
|||
// let _: A<{produces_literal!()}>;
|
||||
// ```
|
||||
// FIXME(const_generics): handle paths when #67075 is fixed.
|
||||
if let [stmt] = inner.stmts.as_slice() {
|
||||
if let ast::StmtKind::Expr(ref expr) = stmt.kind {
|
||||
if !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
|
||||
&& (ctx != UnusedDelimsCtx::AnonConst
|
||||
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
|
||||
&& !expr.span.from_expansion()))
|
||||
&& ctx != UnusedDelimsCtx::ClosureBody
|
||||
&& !cx.sess().source_map().is_multiline(value.span)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
&& !inner.span.from_expansion()
|
||||
{
|
||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
|
||||
}
|
||||
}
|
||||
if let [stmt] = inner.stmts.as_slice()
|
||||
&& let ast::StmtKind::Expr(ref expr) = stmt.kind
|
||||
&& !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
|
||||
&& (ctx != UnusedDelimsCtx::AnonConst
|
||||
|| (matches!(expr.kind, ast::ExprKind::Lit(_))
|
||||
&& !expr.span.from_expansion()))
|
||||
&& ctx != UnusedDelimsCtx::ClosureBody
|
||||
&& !cx.sess().source_map().is_multiline(value.span)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
&& !inner.span.from_expansion()
|
||||
{
|
||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Let(_, ref expr, _, _) => {
|
||||
|
|
|
|||
|
|
@ -370,12 +370,11 @@ impl<'a> CrateLocator<'a> {
|
|||
return self.find_commandline_library(crate_rejections);
|
||||
}
|
||||
let mut seen_paths = FxHashSet::default();
|
||||
if let Some(extra_filename) = self.extra_filename {
|
||||
if let library @ Some(_) =
|
||||
if let Some(extra_filename) = self.extra_filename
|
||||
&& let library @ Some(_) =
|
||||
self.find_library_crate(crate_rejections, extra_filename, &mut seen_paths)?
|
||||
{
|
||||
return Ok(library);
|
||||
}
|
||||
{
|
||||
return Ok(library);
|
||||
}
|
||||
self.find_library_crate(crate_rejections, "", &mut seen_paths)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2136,10 +2136,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
.push((id.owner_id.def_id.local_def_index, simplified_self_ty));
|
||||
|
||||
let trait_def = tcx.trait_def(trait_ref.def_id);
|
||||
if let Ok(mut an) = trait_def.ancestors(tcx, def_id) {
|
||||
if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
|
||||
self.tables.impl_parent.set_some(def_id.index, parent.into());
|
||||
}
|
||||
if let Ok(mut an) = trait_def.ancestors(tcx, def_id)
|
||||
&& let Some(specialization_graph::Node::Impl(parent)) = an.nth(1)
|
||||
{
|
||||
self.tables.impl_parent.set_some(def_id.index, parent.into());
|
||||
}
|
||||
|
||||
// if this is an impl of `CoerceUnsized`, create its
|
||||
|
|
|
|||
|
|
@ -175,23 +175,22 @@ impl Scope {
|
|||
return DUMMY_SP;
|
||||
};
|
||||
let span = tcx.hir_span(hir_id);
|
||||
if let ScopeData::Remainder(first_statement_index) = self.data {
|
||||
if let Node::Block(blk) = tcx.hir_node(hir_id) {
|
||||
// Want span for scope starting after the
|
||||
// indexed statement and ending at end of
|
||||
// `blk`; reuse span of `blk` and shift `lo`
|
||||
// forward to end of indexed statement.
|
||||
//
|
||||
// (This is the special case alluded to in the
|
||||
// doc-comment for this method)
|
||||
if let ScopeData::Remainder(first_statement_index) = self.data
|
||||
// Want span for scope starting after the
|
||||
// indexed statement and ending at end of
|
||||
// `blk`; reuse span of `blk` and shift `lo`
|
||||
// forward to end of indexed statement.
|
||||
//
|
||||
// (This is the special case alluded to in the
|
||||
// doc-comment for this method)
|
||||
&& let Node::Block(blk) = tcx.hir_node(hir_id)
|
||||
{
|
||||
let stmt_span = blk.stmts[first_statement_index.index()].span;
|
||||
|
||||
let stmt_span = blk.stmts[first_statement_index.index()].span;
|
||||
|
||||
// To avoid issues with macro-generated spans, the span
|
||||
// of the statement must be nested in that of the block.
|
||||
if span.lo() <= stmt_span.lo() && stmt_span.lo() <= span.hi() {
|
||||
return span.with_lo(stmt_span.lo());
|
||||
}
|
||||
// To avoid issues with macro-generated spans, the span
|
||||
// of the statement must be nested in that of the block.
|
||||
if span.lo() <= stmt_span.lo() && stmt_span.lo() <= span.hi() {
|
||||
return span.with_lo(stmt_span.lo());
|
||||
}
|
||||
}
|
||||
span
|
||||
|
|
|
|||
|
|
@ -566,10 +566,10 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
let mut prev_discr = None::<Discr<'tcx>>;
|
||||
self.variants().iter_enumerated().map(move |(i, v)| {
|
||||
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
|
||||
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
||||
if let Ok(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
|
||||
discr = new_discr;
|
||||
}
|
||||
if let VariantDiscr::Explicit(expr_did) = v.discr
|
||||
&& let Ok(new_discr) = self.eval_explicit_discr(tcx, expr_did)
|
||||
{
|
||||
discr = new_discr;
|
||||
}
|
||||
prev_discr = Some(discr);
|
||||
|
||||
|
|
|
|||
|
|
@ -1055,11 +1055,11 @@ where
|
|||
_ => Some(this),
|
||||
};
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
if let Some(variant) = data_variant
|
||||
// We're not interested in any unions.
|
||||
if let FieldsShape::Union(_) = variant.fields {
|
||||
data_variant = None;
|
||||
}
|
||||
&& let FieldsShape::Union(_) = variant.fields
|
||||
{
|
||||
data_variant = None;
|
||||
}
|
||||
|
||||
let mut result = None;
|
||||
|
|
|
|||
|
|
@ -225,10 +225,10 @@ impl<'tcx> RegionHighlightMode<'tcx> {
|
|||
region: Option<ty::Region<'tcx>>,
|
||||
number: Option<usize>,
|
||||
) {
|
||||
if let Some(k) = region {
|
||||
if let Some(n) = number {
|
||||
self.highlighting_region(k, n);
|
||||
}
|
||||
if let Some(k) = region
|
||||
&& let Some(n) = number
|
||||
{
|
||||
self.highlighting_region(k, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,28 +76,24 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
let mut pattern = self.pattern_from_hir(local.pat);
|
||||
debug!(?pattern);
|
||||
|
||||
if let Some(ty) = &local.ty {
|
||||
if let Some(&user_ty) =
|
||||
if let Some(ty) = &local.ty
|
||||
&& let Some(&user_ty) =
|
||||
self.typeck_results.user_provided_types().get(ty.hir_id)
|
||||
{
|
||||
debug!("mirror_stmts: user_ty={:?}", user_ty);
|
||||
let annotation = CanonicalUserTypeAnnotation {
|
||||
user_ty: Box::new(user_ty),
|
||||
span: ty.span,
|
||||
inferred_ty: self.typeck_results.node_type(ty.hir_id),
|
||||
};
|
||||
pattern = Box::new(Pat {
|
||||
ty: pattern.ty,
|
||||
span: pattern.span,
|
||||
kind: PatKind::AscribeUserType {
|
||||
ascription: Ascription {
|
||||
annotation,
|
||||
variance: ty::Covariant,
|
||||
},
|
||||
subpattern: pattern,
|
||||
},
|
||||
});
|
||||
}
|
||||
{
|
||||
debug!("mirror_stmts: user_ty={:?}", user_ty);
|
||||
let annotation = CanonicalUserTypeAnnotation {
|
||||
user_ty: Box::new(user_ty),
|
||||
span: ty.span,
|
||||
inferred_ty: self.typeck_results.node_type(ty.hir_id),
|
||||
};
|
||||
pattern = Box::new(Pat {
|
||||
ty: pattern.ty,
|
||||
span: pattern.span,
|
||||
kind: PatKind::AscribeUserType {
|
||||
ascription: Ascription { annotation, variance: ty::Covariant },
|
||||
subpattern: pattern,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let span = match local.init {
|
||||
|
|
|
|||
|
|
@ -105,11 +105,11 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
// // ^ error message points at this expression.
|
||||
// }
|
||||
let mut adjust_span = |expr: &mut Expr<'tcx>| {
|
||||
if let ExprKind::Block { block } = expr.kind {
|
||||
if let Some(last_expr) = self.thir[block].expr {
|
||||
span = self.thir[last_expr].span;
|
||||
expr.span = span;
|
||||
}
|
||||
if let ExprKind::Block { block } = expr.kind
|
||||
&& let Some(last_expr) = self.thir[block].expr
|
||||
{
|
||||
span = self.thir[last_expr].span;
|
||||
expr.span = span;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -956,10 +956,10 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
};
|
||||
|
||||
fn local(expr: &rustc_hir::Expr<'_>) -> Option<hir::HirId> {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
|
||||
if let Res::Local(hir_id) = path.res {
|
||||
return Some(hir_id);
|
||||
}
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
|
||||
&& let Res::Local(hir_id) = path.res
|
||||
{
|
||||
return Some(hir_id);
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
|||
|
|
@ -1155,14 +1155,12 @@ fn find_fallback_pattern_typo<'tcx>(
|
|||
}
|
||||
hir::Node::Block(hir::Block { stmts, .. }) => {
|
||||
for stmt in *stmts {
|
||||
if let hir::StmtKind::Let(let_stmt) = stmt.kind {
|
||||
if let hir::PatKind::Binding(_, _, binding_name, _) =
|
||||
if let hir::StmtKind::Let(let_stmt) = stmt.kind
|
||||
&& let hir::PatKind::Binding(_, _, binding_name, _) =
|
||||
let_stmt.pat.kind
|
||||
{
|
||||
if name == binding_name.name {
|
||||
lint.pattern_let_binding = Some(binding_name.span);
|
||||
}
|
||||
}
|
||||
&& name == binding_name.name
|
||||
{
|
||||
lint.pattern_let_binding = Some(binding_name.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,10 +124,9 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
|
|||
// Drop does not count as a move but we should still consider the variable uninitialized.
|
||||
if let Some(Terminator { kind: TerminatorKind::Drop { place, .. }, .. }) =
|
||||
body.stmt_at(loc).right()
|
||||
&& let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref())
|
||||
{
|
||||
if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) {
|
||||
on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
|
||||
}
|
||||
on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
|
||||
}
|
||||
|
||||
debug!("drop_flag_effects: assignment for location({:?})", loc);
|
||||
|
|
|
|||
|
|
@ -637,16 +637,13 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
|
|||
debug!("initializes move_indexes {:?}", init_loc_map[location]);
|
||||
state.gen_all(init_loc_map[location].iter().copied());
|
||||
|
||||
if let mir::StatementKind::StorageDead(local) = stmt.kind {
|
||||
if let mir::StatementKind::StorageDead(local) = stmt.kind
|
||||
// End inits for StorageDead, so that an immutable variable can
|
||||
// be reinitialized on the next iteration of the loop.
|
||||
if let Some(move_path_index) = rev_lookup.find_local(local) {
|
||||
debug!(
|
||||
"clears the ever initialized status of {:?}",
|
||||
init_path_map[move_path_index]
|
||||
);
|
||||
state.kill_all(init_path_map[move_path_index].iter().copied());
|
||||
}
|
||||
&& let Some(move_path_index) = rev_lookup.find_local(local)
|
||||
{
|
||||
debug!("clears the ever initialized status of {:?}", init_path_map[move_path_index]);
|
||||
state.kill_all(init_path_map[move_path_index].iter().copied());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,12 +135,11 @@ fn value_assigned_to_local<'a, 'tcx>(
|
|||
stmt: &'a mir::Statement<'tcx>,
|
||||
local: Local,
|
||||
) -> Option<&'a mir::Rvalue<'tcx>> {
|
||||
if let mir::StatementKind::Assign(box (place, rvalue)) = &stmt.kind {
|
||||
if let Some(l) = place.as_local() {
|
||||
if local == l {
|
||||
return Some(&*rvalue);
|
||||
}
|
||||
}
|
||||
if let mir::StatementKind::Assign(box (place, rvalue)) = &stmt.kind
|
||||
&& let Some(l) = place.as_local()
|
||||
&& local == l
|
||||
{
|
||||
return Some(&*rvalue);
|
||||
}
|
||||
|
||||
None
|
||||
|
|
@ -178,31 +177,30 @@ impl PeekCall {
|
|||
let span = terminator.source_info.span;
|
||||
if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
|
||||
&terminator.kind
|
||||
&& let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind()
|
||||
{
|
||||
if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() {
|
||||
if tcx.intrinsic(def_id)?.name != sym::rustc_peek {
|
||||
return None;
|
||||
}
|
||||
if tcx.intrinsic(def_id)?.name != sym::rustc_peek {
|
||||
return None;
|
||||
}
|
||||
|
||||
assert_eq!(fn_args.len(), 1);
|
||||
let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0));
|
||||
let arg = match &args[0].node {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
tcx.dcx().emit_err(PeekMustBeNotTemporary { span });
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(fn_args.len(), 1);
|
||||
let kind = PeekCallKind::from_arg_ty(fn_args.type_at(0));
|
||||
let arg = match &args[0].node {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if let Some(local) = place.as_local() {
|
||||
local
|
||||
} else {
|
||||
tcx.dcx().emit_err(PeekMustBeNotTemporary { span });
|
||||
return None;
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().emit_err(PeekMustBeNotTemporary { span });
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
return Some(PeekCall { arg, kind, span });
|
||||
}
|
||||
return Some(PeekCall { arg, kind, span });
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
|||
|
|
@ -215,10 +215,10 @@ impl<V: Clone + HasBottom> State<V> {
|
|||
// If both places are tracked, we copy the value to the target.
|
||||
// If the target is tracked, but the source is not, we do nothing, as invalidation has
|
||||
// already been performed.
|
||||
if let Some(target_value) = map.places[target].value_index {
|
||||
if let Some(source_value) = map.places[source].value_index {
|
||||
values.insert(target_value, values.get(source_value).clone());
|
||||
}
|
||||
if let Some(target_value) = map.places[target].value_index
|
||||
&& let Some(source_value) = map.places[source].value_index
|
||||
{
|
||||
values.insert(target_value, values.get(source_value).clone());
|
||||
}
|
||||
for target_child in map.children(target) {
|
||||
// Try to find corresponding child and recurse. Reasoning is similar as above.
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ impl<'tcx> MutVisitor<'tcx> for FixReturnPendingVisitor<'tcx> {
|
|||
}
|
||||
|
||||
// Converting `_0 = Poll::<Rv>::Pending` to `_0 = Poll::<()>::Pending`
|
||||
if let Rvalue::Aggregate(kind, _) = rvalue {
|
||||
if let AggregateKind::Adt(_, _, ref mut args, _, _) = **kind {
|
||||
*args = self.tcx.mk_args(&[self.tcx.types.unit.into()]);
|
||||
}
|
||||
if let Rvalue::Aggregate(kind, _) = rvalue
|
||||
&& let AggregateKind::Adt(_, _, ref mut args, _, _) = **kind
|
||||
{
|
||||
*args = self.tcx.mk_args(&[self.tcx.types.unit.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -997,12 +997,11 @@ fn promote_candidates<'tcx>(
|
|||
for candidate in candidates.into_iter().rev() {
|
||||
let Location { block, statement_index } = candidate.location;
|
||||
if let StatementKind::Assign(box (place, _)) = &body[block].statements[statement_index].kind
|
||||
&& let Some(local) = place.as_local()
|
||||
{
|
||||
if let Some(local) = place.as_local() {
|
||||
if temps[local] == TempState::PromotedOut {
|
||||
// Already promoted.
|
||||
continue;
|
||||
}
|
||||
if temps[local] == TempState::PromotedOut {
|
||||
// Already promoted.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1066,11 +1065,11 @@ fn promote_candidates<'tcx>(
|
|||
_ => true,
|
||||
});
|
||||
let terminator = block.terminator_mut();
|
||||
if let TerminatorKind::Drop { place, target, .. } = &terminator.kind {
|
||||
if let Some(index) = place.as_local() {
|
||||
if promoted(index) {
|
||||
terminator.kind = TerminatorKind::Goto { target: *target };
|
||||
}
|
||||
if let TerminatorKind::Drop { place, target, .. } = &terminator.kind
|
||||
&& let Some(index) = place.as_local()
|
||||
{
|
||||
if promoted(index) {
|
||||
terminator.kind = TerminatorKind::Goto { target: *target };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,14 +48,13 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
|
|||
let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
|
||||
for bb in postorder {
|
||||
debug!(" processing {:?}", bb);
|
||||
if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
|
||||
if let UnwindAction::Cleanup(unwind_bb) = *unwind {
|
||||
if nop_landing_pads.contains(unwind_bb) {
|
||||
debug!(" removing noop landing pad");
|
||||
landing_pads_removed += 1;
|
||||
*unwind = UnwindAction::Continue;
|
||||
}
|
||||
}
|
||||
if let Some(unwind) = body[bb].terminator_mut().unwind_mut()
|
||||
&& let UnwindAction::Cleanup(unwind_bb) = *unwind
|
||||
&& nop_landing_pads.contains(unwind_bb)
|
||||
{
|
||||
debug!(" removing noop landing pad");
|
||||
landing_pads_removed += 1;
|
||||
*unwind = UnwindAction::Continue;
|
||||
}
|
||||
|
||||
body[bb].terminator_mut().successors_mut(|target| {
|
||||
|
|
|
|||
|
|
@ -80,15 +80,14 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
|
|||
cfg_checker.fail(location, msg);
|
||||
}
|
||||
|
||||
if let MirPhase::Runtime(_) = body.phase {
|
||||
if let ty::InstanceKind::Item(_) = body.source.instance {
|
||||
if body.has_free_regions() {
|
||||
cfg_checker.fail(
|
||||
Location::START,
|
||||
format!("Free regions in optimized {} MIR", body.phase.name()),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let MirPhase::Runtime(_) = body.phase
|
||||
&& let ty::InstanceKind::Item(_) = body.source.instance
|
||||
&& body.has_free_regions()
|
||||
{
|
||||
cfg_checker.fail(
|
||||
Location::START,
|
||||
format!("Free regions in optimized {} MIR", body.phase.name()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1178,12 +1178,11 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio
|
|||
let autodiff_items = tcx.arena.alloc_from_iter(autodiff_items);
|
||||
|
||||
// Output monomorphization stats per def_id
|
||||
if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
|
||||
if let Err(err) =
|
||||
if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats
|
||||
&& let Err(err) =
|
||||
dump_mono_items_stats(tcx, codegen_units, path, tcx.crate_name(LOCAL_CRATE))
|
||||
{
|
||||
tcx.dcx().emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
|
||||
}
|
||||
{
|
||||
tcx.dcx().emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
|
||||
}
|
||||
|
||||
if tcx.sess.opts.unstable_opts.print_mono_items {
|
||||
|
|
|
|||
|
|
@ -1973,21 +1973,21 @@ impl<'a> Parser<'a> {
|
|||
format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token));
|
||||
|
||||
// Try to recover extra trailing angle brackets
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
|
||||
if let Some(last_segment) = segments.last() {
|
||||
let guar = self.check_trailing_angle_brackets(
|
||||
last_segment,
|
||||
&[exp!(Comma), exp!(CloseBrace)],
|
||||
);
|
||||
if let Some(_guar) = guar {
|
||||
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
|
||||
// after the comma
|
||||
let _ = self.eat(exp!(Comma));
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind
|
||||
&& let Some(last_segment) = segments.last()
|
||||
{
|
||||
let guar = self.check_trailing_angle_brackets(
|
||||
last_segment,
|
||||
&[exp!(Comma), exp!(CloseBrace)],
|
||||
);
|
||||
if let Some(_guar) = guar {
|
||||
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
|
||||
// after the comma
|
||||
let _ = self.eat(exp!(Comma));
|
||||
|
||||
// `check_trailing_angle_brackets` already emitted a nicer error, as
|
||||
// proven by the presence of `_guar`. We can continue parsing.
|
||||
return Ok(a_var);
|
||||
}
|
||||
// `check_trailing_angle_brackets` already emitted a nicer error, as
|
||||
// proven by the presence of `_guar`. We can continue parsing.
|
||||
return Ok(a_var);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3034,18 +3034,16 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if let Ok(t) = &ty {
|
||||
// Check for trailing angle brackets
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &t.kind {
|
||||
if let Some(segment) = segments.last() {
|
||||
if let Some(guar) =
|
||||
this.check_trailing_angle_brackets(segment, &[exp!(CloseParen)])
|
||||
{
|
||||
return Ok((
|
||||
dummy_arg(segment.ident, guar),
|
||||
Trailing::No,
|
||||
UsePreAttrPos::No,
|
||||
));
|
||||
}
|
||||
}
|
||||
if let TyKind::Path(_, Path { segments, .. }) = &t.kind
|
||||
&& let Some(segment) = segments.last()
|
||||
&& let Some(guar) =
|
||||
this.check_trailing_angle_brackets(segment, &[exp!(CloseParen)])
|
||||
{
|
||||
return Ok((
|
||||
dummy_arg(segment.ident, guar),
|
||||
Trailing::No,
|
||||
UsePreAttrPos::No,
|
||||
));
|
||||
}
|
||||
|
||||
if this.token != token::Comma && this.token != token::CloseParen {
|
||||
|
|
|
|||
|
|
@ -104,10 +104,10 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
|
|||
|
||||
fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
|
||||
for (op, _) in asm.operands {
|
||||
if let hir::InlineAsmOperand::SymStatic { def_id, .. } = op {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
self.reachable_symbols.insert(def_id);
|
||||
}
|
||||
if let hir::InlineAsmOperand::SymStatic { def_id, .. } = op
|
||||
&& let Some(def_id) = def_id.as_local()
|
||||
{
|
||||
self.reachable_symbols.insert(def_id);
|
||||
}
|
||||
}
|
||||
intravisit::walk_inline_asm(self, asm, id);
|
||||
|
|
|
|||
|
|
@ -929,10 +929,10 @@ struct CheckTraitImplStable<'tcx> {
|
|||
|
||||
impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
|
||||
fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: hir::HirId) {
|
||||
if let Some(def_id) = path.res.opt_def_id() {
|
||||
if let Some(stab) = self.tcx.lookup_stability(def_id) {
|
||||
self.fully_stable &= stab.level.is_stable();
|
||||
}
|
||||
if let Some(def_id) = path.res.opt_def_id()
|
||||
&& let Some(stab) = self.tcx.lookup_stability(def_id)
|
||||
{
|
||||
self.fully_stable &= stab.level.is_stable();
|
||||
}
|
||||
intravisit::walk_path(self, path)
|
||||
}
|
||||
|
|
@ -1055,10 +1055,10 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
// implications from this crate.
|
||||
remaining_implications.remove(&feature);
|
||||
|
||||
if let FeatureStability::Unstable { old_name: Some(alias) } = stability {
|
||||
if let Some(span) = remaining_lib_features.swap_remove(&alias) {
|
||||
tcx.dcx().emit_err(errors::RenamedFeature { span, feature, alias });
|
||||
}
|
||||
if let FeatureStability::Unstable { old_name: Some(alias) } = stability
|
||||
&& let Some(span) = remaining_lib_features.swap_remove(&alias)
|
||||
{
|
||||
tcx.dcx().emit_err(errors::RenamedFeature { span, feature, alias });
|
||||
}
|
||||
|
||||
if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
|
||||
|
|
|
|||
|
|
@ -75,19 +75,19 @@ impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Closure(closure) = expr.kind {
|
||||
if let Some(upvars) = self.tcx.upvars_mentioned(closure.def_id) {
|
||||
// Every capture of a closure expression is a local in scope,
|
||||
// that is moved/copied/borrowed into the closure value, and
|
||||
// for this analysis they are like any other access to a local.
|
||||
//
|
||||
// E.g. in `|b| |c| (a, b, c)`, the upvars of the inner closure
|
||||
// are `a` and `b`, and while `a` is not directly used in the
|
||||
// outer closure, it needs to be an upvar there too, so that
|
||||
// the inner closure can take it (from the outer closure's env).
|
||||
for (&var_id, upvar) in upvars {
|
||||
self.visit_local_use(var_id, upvar.span);
|
||||
}
|
||||
if let hir::ExprKind::Closure(closure) = expr.kind
|
||||
&& let Some(upvars) = self.tcx.upvars_mentioned(closure.def_id)
|
||||
{
|
||||
// Every capture of a closure expression is a local in scope,
|
||||
// that is moved/copied/borrowed into the closure value, and
|
||||
// for this analysis they are like any other access to a local.
|
||||
//
|
||||
// E.g. in `|b| |c| (a, b, c)`, the upvars of the inner closure
|
||||
// are `a` and `b`, and while `a` is not directly used in the
|
||||
// outer closure, it needs to be an upvar there too, so that
|
||||
// the inner closure can take it (from the outer closure's env).
|
||||
for (&var_id, upvar) in upvars {
|
||||
self.visit_local_use(var_id, upvar.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,12 +204,10 @@ where
|
|||
// Something like `fn() {my_method}` type of the method
|
||||
// `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
|
||||
// so we need to visit the self type additionally.
|
||||
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
|
||||
if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
|
||||
try_visit!(
|
||||
tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
|
||||
);
|
||||
}
|
||||
if let Some(assoc_item) = tcx.opt_associated_item(def_id)
|
||||
&& let Some(impl_def_id) = assoc_item.impl_container(tcx)
|
||||
{
|
||||
try_visit!(tcx.type_of(impl_def_id).instantiate_identity().visit_with(self));
|
||||
}
|
||||
}
|
||||
ty::Alias(kind @ (ty::Inherent | ty::Free | ty::Projection), data) => {
|
||||
|
|
@ -734,6 +732,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
|||
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
|
||||
self.update(ctor_def_id, variant_ev, Level::Reachable);
|
||||
}
|
||||
|
||||
for field in variant.data.fields() {
|
||||
self.update(field.def_id, variant_ev, Level::Reachable);
|
||||
self.reach(field.def_id, variant_ev).ty();
|
||||
|
|
|
|||
|
|
@ -498,12 +498,12 @@ impl<D: Deps> DepGraph<D> {
|
|||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if let Some(target) = task_deps.node {
|
||||
if let Some(ref forbidden_edge) = data.current.forbidden_edge {
|
||||
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
|
||||
if forbidden_edge.test(&src, &target) {
|
||||
panic!("forbidden edge {:?} -> {:?} created", src, target)
|
||||
}
|
||||
if let Some(target) = task_deps.node
|
||||
&& let Some(ref forbidden_edge) = data.current.forbidden_edge
|
||||
{
|
||||
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
|
||||
if forbidden_edge.test(&src, &target) {
|
||||
panic!("forbidden edge {:?} -> {:?} created", src, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,10 +289,10 @@ where
|
|||
F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>,
|
||||
{
|
||||
// Visit the parent query which is a non-resumable waiter since it's on the same stack
|
||||
if let Some(parent) = query.parent(query_map) {
|
||||
if let Some(cycle) = visit(query.span(query_map), parent) {
|
||||
return Some(cycle);
|
||||
}
|
||||
if let Some(parent) = query.parent(query_map)
|
||||
&& let Some(cycle) = visit(query.span(query_map), parent)
|
||||
{
|
||||
return Some(cycle);
|
||||
}
|
||||
|
||||
// Visit the explicit waiters which use condvars and are resumable
|
||||
|
|
|
|||
|
|
@ -818,10 +818,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
// If the first argument in call is `self` suggest calling a method.
|
||||
if let Some((call_span, args_span)) = self.call_has_self_arg(source) {
|
||||
let mut args_snippet = String::new();
|
||||
if let Some(args_span) = args_span {
|
||||
if let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(args_span) {
|
||||
args_snippet = snippet;
|
||||
}
|
||||
if let Some(args_span) = args_span
|
||||
&& let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(args_span)
|
||||
{
|
||||
args_snippet = snippet;
|
||||
}
|
||||
|
||||
err.span_suggestion(
|
||||
|
|
@ -955,59 +955,57 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)),
|
||||
false,
|
||||
) = (source, res, is_macro)
|
||||
{
|
||||
if let Some(bounds @ [first_bound, .., last_bound]) =
|
||||
&& let Some(bounds @ [first_bound, .., last_bound]) =
|
||||
self.diag_metadata.current_trait_object
|
||||
{
|
||||
fallback = true;
|
||||
let spans: Vec<Span> = bounds
|
||||
.iter()
|
||||
.map(|bound| bound.span())
|
||||
.filter(|&sp| sp != base_error.span)
|
||||
.collect();
|
||||
{
|
||||
fallback = true;
|
||||
let spans: Vec<Span> = bounds
|
||||
.iter()
|
||||
.map(|bound| bound.span())
|
||||
.filter(|&sp| sp != base_error.span)
|
||||
.collect();
|
||||
|
||||
let start_span = first_bound.span();
|
||||
// `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
|
||||
let end_span = last_bound.span();
|
||||
// `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
|
||||
let last_bound_span = spans.last().cloned().unwrap();
|
||||
let mut multi_span: MultiSpan = spans.clone().into();
|
||||
for sp in spans {
|
||||
let msg = if sp == last_bound_span {
|
||||
format!(
|
||||
"...because of {these} bound{s}",
|
||||
these = pluralize!("this", bounds.len() - 1),
|
||||
s = pluralize!(bounds.len() - 1),
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
multi_span.push_span_label(sp, msg);
|
||||
}
|
||||
multi_span.push_span_label(base_error.span, "expected this type to be a trait...");
|
||||
err.span_help(
|
||||
multi_span,
|
||||
"`+` is used to constrain a \"trait object\" type with lifetimes or \
|
||||
let start_span = first_bound.span();
|
||||
// `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
|
||||
let end_span = last_bound.span();
|
||||
// `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
|
||||
let last_bound_span = spans.last().cloned().unwrap();
|
||||
let mut multi_span: MultiSpan = spans.clone().into();
|
||||
for sp in spans {
|
||||
let msg = if sp == last_bound_span {
|
||||
format!(
|
||||
"...because of {these} bound{s}",
|
||||
these = pluralize!("this", bounds.len() - 1),
|
||||
s = pluralize!(bounds.len() - 1),
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
multi_span.push_span_label(sp, msg);
|
||||
}
|
||||
multi_span.push_span_label(base_error.span, "expected this type to be a trait...");
|
||||
err.span_help(
|
||||
multi_span,
|
||||
"`+` is used to constrain a \"trait object\" type with lifetimes or \
|
||||
auto-traits; structs and enums can't be bound in that way",
|
||||
);
|
||||
if bounds.iter().all(|bound| match bound {
|
||||
ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true,
|
||||
ast::GenericBound::Trait(tr) => tr.span == base_error.span,
|
||||
}) {
|
||||
let mut sugg = vec![];
|
||||
if base_error.span != start_span {
|
||||
sugg.push((start_span.until(base_error.span), String::new()));
|
||||
}
|
||||
if base_error.span != end_span {
|
||||
sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new()));
|
||||
}
|
||||
|
||||
err.multipart_suggestion(
|
||||
"if you meant to use a type and not a trait here, remove the bounds",
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
);
|
||||
if bounds.iter().all(|bound| match bound {
|
||||
ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true,
|
||||
ast::GenericBound::Trait(tr) => tr.span == base_error.span,
|
||||
}) {
|
||||
let mut sugg = vec![];
|
||||
if base_error.span != start_span {
|
||||
sugg.push((start_span.until(base_error.span), String::new()));
|
||||
}
|
||||
if base_error.span != end_span {
|
||||
sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new()));
|
||||
}
|
||||
|
||||
err.multipart_suggestion(
|
||||
"if you meant to use a type and not a trait here, remove the bounds",
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1151,13 +1149,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
err.code(E0411);
|
||||
err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
|
||||
if let Some(item) = self.diag_metadata.current_item {
|
||||
if let Some(ident) = item.kind.ident() {
|
||||
err.span_label(
|
||||
ident.span,
|
||||
format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
|
||||
);
|
||||
}
|
||||
if let Some(item) = self.diag_metadata.current_item
|
||||
&& let Some(ident) = item.kind.ident()
|
||||
{
|
||||
err.span_label(
|
||||
ident.span,
|
||||
format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
|
||||
);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
@ -1934,11 +1932,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
};
|
||||
|
||||
let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
|
||||
if let PathSource::Expr(Some(parent)) = source {
|
||||
if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
|
||||
bad_struct_syntax_suggestion(self, err, def_id);
|
||||
return true;
|
||||
}
|
||||
if let PathSource::Expr(Some(parent)) = source
|
||||
&& let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind
|
||||
{
|
||||
bad_struct_syntax_suggestion(self, err, def_id);
|
||||
return true;
|
||||
}
|
||||
struct_ctor
|
||||
} else {
|
||||
|
|
@ -2347,19 +2345,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
|
||||
if let Some(node_id) =
|
||||
self.diag_metadata.current_self_type.as_ref().and_then(extract_node_id)
|
||||
&& let Some(resolution) = self.r.partial_res_map.get(&node_id)
|
||||
&& let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) = resolution.full_res()
|
||||
&& let Some(fields) = self.r.field_idents(did)
|
||||
&& let Some(field) = fields.iter().find(|id| ident.name == id.name)
|
||||
{
|
||||
// Look for a field with the same name in the current self_type.
|
||||
if let Some(resolution) = self.r.partial_res_map.get(&node_id) {
|
||||
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
|
||||
resolution.full_res()
|
||||
{
|
||||
if let Some(fields) = self.r.field_idents(did) {
|
||||
if let Some(field) = fields.iter().find(|id| ident.name == id.name) {
|
||||
return Some(AssocSuggestion::Field(field.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(AssocSuggestion::Field(field.span));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2394,44 +2386,44 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
|
||||
// Look for associated items in the current trait.
|
||||
if let Some((module, _)) = self.current_trait_ref {
|
||||
if let Ok(binding) = self.r.maybe_resolve_ident_in_module(
|
||||
if let Some((module, _)) = self.current_trait_ref
|
||||
&& let Ok(binding) = self.r.maybe_resolve_ident_in_module(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
ident,
|
||||
ns,
|
||||
&self.parent_scope,
|
||||
None,
|
||||
) {
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
match res {
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
|
||||
let has_self = match def_id.as_local() {
|
||||
Some(def_id) => self
|
||||
.r
|
||||
.delegation_fn_sigs
|
||||
.get(&def_id)
|
||||
.is_some_and(|sig| sig.has_self),
|
||||
None => {
|
||||
self.r.tcx.fn_arg_idents(def_id).first().is_some_and(|&ident| {
|
||||
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
|
||||
})
|
||||
}
|
||||
};
|
||||
if has_self {
|
||||
return Some(AssocSuggestion::MethodWithSelf { called });
|
||||
} else {
|
||||
return Some(AssocSuggestion::AssocFn { called });
|
||||
)
|
||||
{
|
||||
let res = binding.res();
|
||||
if filter_fn(res) {
|
||||
match res {
|
||||
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
|
||||
let has_self = match def_id.as_local() {
|
||||
Some(def_id) => self
|
||||
.r
|
||||
.delegation_fn_sigs
|
||||
.get(&def_id)
|
||||
.is_some_and(|sig| sig.has_self),
|
||||
None => {
|
||||
self.r.tcx.fn_arg_idents(def_id).first().is_some_and(|&ident| {
|
||||
matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
|
||||
})
|
||||
}
|
||||
};
|
||||
if has_self {
|
||||
return Some(AssocSuggestion::MethodWithSelf { called });
|
||||
} else {
|
||||
return Some(AssocSuggestion::AssocFn { called });
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, _) => {
|
||||
return Some(AssocSuggestion::AssocConst);
|
||||
}
|
||||
Res::Def(DefKind::AssocTy, _) => {
|
||||
return Some(AssocSuggestion::AssocType);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, _) => {
|
||||
return Some(AssocSuggestion::AssocConst);
|
||||
}
|
||||
Res::Def(DefKind::AssocTy, _) => {
|
||||
return Some(AssocSuggestion::AssocType);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1023,40 +1023,39 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
node_id: NodeId,
|
||||
) {
|
||||
let span = path.span;
|
||||
if let Some(stability) = &ext.stability {
|
||||
if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. } =
|
||||
if let Some(stability) = &ext.stability
|
||||
&& let StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. } =
|
||||
stability.level
|
||||
{
|
||||
let feature = stability.feature;
|
||||
{
|
||||
let feature = stability.feature;
|
||||
|
||||
let is_allowed =
|
||||
|feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
|
||||
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
|
||||
if !is_allowed(feature) && !allowed_by_implication {
|
||||
let lint_buffer = &mut self.lint_buffer;
|
||||
let soft_handler = |lint, span, msg: String| {
|
||||
lint_buffer.buffer_lint(
|
||||
lint,
|
||||
node_id,
|
||||
span,
|
||||
BuiltinLintDiag::UnstableFeature(
|
||||
// FIXME make this translatable
|
||||
msg.into(),
|
||||
),
|
||||
)
|
||||
};
|
||||
stability::report_unstable(
|
||||
self.tcx.sess,
|
||||
feature,
|
||||
reason.to_opt_reason(),
|
||||
issue,
|
||||
None,
|
||||
is_soft,
|
||||
let is_allowed =
|
||||
|feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
|
||||
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
|
||||
if !is_allowed(feature) && !allowed_by_implication {
|
||||
let lint_buffer = &mut self.lint_buffer;
|
||||
let soft_handler = |lint, span, msg: String| {
|
||||
lint_buffer.buffer_lint(
|
||||
lint,
|
||||
node_id,
|
||||
span,
|
||||
soft_handler,
|
||||
stability::UnstableKind::Regular,
|
||||
);
|
||||
}
|
||||
BuiltinLintDiag::UnstableFeature(
|
||||
// FIXME make this translatable
|
||||
msg.into(),
|
||||
),
|
||||
)
|
||||
};
|
||||
stability::report_unstable(
|
||||
self.tcx.sess,
|
||||
feature,
|
||||
reason.to_opt_reason(),
|
||||
issue,
|
||||
None,
|
||||
is_soft,
|
||||
span,
|
||||
soft_handler,
|
||||
stability::UnstableKind::Regular,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(depr) = &ext.deprecation {
|
||||
|
|
|
|||
|
|
@ -107,10 +107,10 @@ pub fn feature_err_issue(
|
|||
let span = span.into();
|
||||
|
||||
// Cancel an earlier warning for this same error, if it exists.
|
||||
if let Some(span) = span.primary_span() {
|
||||
if let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) {
|
||||
err.cancel()
|
||||
}
|
||||
if let Some(span) = span.primary_span()
|
||||
&& let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning)
|
||||
{
|
||||
err.cancel()
|
||||
}
|
||||
|
||||
let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() });
|
||||
|
|
|
|||
|
|
@ -1363,11 +1363,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
|||
sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() });
|
||||
}
|
||||
|
||||
if let Some(flavor) = sess.opts.cg.linker_flavor {
|
||||
if let Some(compatible_list) = sess.target.linker_flavor.check_compatibility(flavor) {
|
||||
let flavor = flavor.desc();
|
||||
sess.dcx().emit_err(errors::IncompatibleLinkerFlavor { flavor, compatible_list });
|
||||
}
|
||||
if let Some(flavor) = sess.opts.cg.linker_flavor
|
||||
&& let Some(compatible_list) = sess.target.linker_flavor.check_compatibility(flavor)
|
||||
{
|
||||
let flavor = flavor.desc();
|
||||
sess.dcx().emit_err(errors::IncompatibleLinkerFlavor { flavor, compatible_list });
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.function_return != FunctionReturn::default() {
|
||||
|
|
|
|||
|
|
@ -826,10 +826,10 @@ impl SourceMap {
|
|||
/// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
|
||||
/// `c`.
|
||||
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
|
||||
if let Ok(snippet) = self.span_to_snippet(sp) {
|
||||
if let Some(offset) = snippet.find(c) {
|
||||
return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
|
||||
}
|
||||
if let Ok(snippet) = self.span_to_snippet(sp)
|
||||
&& let Some(offset) = snippet.find(c)
|
||||
{
|
||||
return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
|
|
|||
|
|
@ -314,16 +314,15 @@ fn classify_arg<'a, Ty, C>(
|
|||
}
|
||||
|
||||
fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
|
||||
if let Primitive::Int(i, _) = scalar.primitive() {
|
||||
// 32-bit integers are always sign-extended
|
||||
if i.size().bits() == 32 && xlen > 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr
|
||||
&& let Primitive::Int(i, _) = scalar.primitive()
|
||||
&& i.size().bits() == 32
|
||||
&& xlen > 32
|
||||
&& let PassMode::Direct(ref mut attrs) = arg.mode
|
||||
{
|
||||
// 32-bit integers are always sign-extended
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
|
||||
arg.extend_integer_width_to(xlen);
|
||||
|
|
|
|||
|
|
@ -6,15 +6,14 @@ use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform
|
|||
|
||||
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
|
||||
// Always sign extend u32 values on 64-bit mips
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
|
||||
if let Primitive::Int(i, signed) = scalar.primitive() {
|
||||
if !signed && i.size().bits() == 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr
|
||||
&& let Primitive::Int(i, signed) = scalar.primitive()
|
||||
&& !signed
|
||||
&& i.size().bits() == 32
|
||||
&& let PassMode::Direct(ref mut attrs) = arg.mode
|
||||
{
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
|
||||
arg.extend_integer_width_to(bits);
|
||||
|
|
@ -58,13 +57,12 @@ where
|
|||
ret.cast_to(reg);
|
||||
return;
|
||||
}
|
||||
} else if ret.layout.fields.count() == 2 {
|
||||
if let Some(reg0) = float_reg(cx, ret, 0) {
|
||||
if let Some(reg1) = float_reg(cx, ret, 1) {
|
||||
ret.cast_to(CastTarget::pair(reg0, reg1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ret.layout.fields.count() == 2
|
||||
&& let Some(reg0) = float_reg(cx, ret, 0)
|
||||
&& let Some(reg1) = float_reg(cx, ret, 1)
|
||||
{
|
||||
ret.cast_to(CastTarget::pair(reg0, reg1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,18 +495,16 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
|||
|
||||
pub fn extend_integer_width_to(&mut self, bits: u64) {
|
||||
// Only integers have signedness
|
||||
if let BackendRepr::Scalar(scalar) = self.layout.backend_repr {
|
||||
if let Primitive::Int(i, signed) = scalar.primitive() {
|
||||
if i.size().bits() < bits {
|
||||
if let PassMode::Direct(ref mut attrs) = self.mode {
|
||||
if signed {
|
||||
attrs.ext(ArgExtension::Sext)
|
||||
} else {
|
||||
attrs.ext(ArgExtension::Zext)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if let BackendRepr::Scalar(scalar) = self.layout.backend_repr
|
||||
&& let Primitive::Int(i, signed) = scalar.primitive()
|
||||
&& i.size().bits() < bits
|
||||
&& let PassMode::Direct(ref mut attrs) = self.mode
|
||||
{
|
||||
if signed {
|
||||
attrs.ext(ArgExtension::Sext)
|
||||
} else {
|
||||
attrs.ext(ArgExtension::Zext)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -393,16 +393,14 @@ fn classify_arg<'a, Ty, C>(
|
|||
}
|
||||
|
||||
fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
|
||||
if let Primitive::Int(i, _) = scalar.primitive() {
|
||||
// 32-bit integers are always sign-extended
|
||||
if i.size().bits() == 32 && xlen > 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr
|
||||
&& let Primitive::Int(i, _) = scalar.primitive()
|
||||
&& i.size().bits() == 32
|
||||
&& xlen > 32
|
||||
&& let PassMode::Direct(ref mut attrs) = arg.mode
|
||||
{
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
return;
|
||||
}
|
||||
|
||||
arg.extend_integer_width_to(xlen);
|
||||
|
|
|
|||
|
|
@ -104,10 +104,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
ty::AssocKind::Fn { .. } => {
|
||||
if let Some(hir_id) =
|
||||
assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id))
|
||||
&& let Some(decl) = self.tcx().hir_fn_decl_by_hir_id(hir_id)
|
||||
{
|
||||
if let Some(decl) = self.tcx().hir_fn_decl_by_hir_id(hir_id) {
|
||||
visitor.visit_fn_decl(decl);
|
||||
}
|
||||
visitor.visit_fn_decl(decl);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -91,51 +91,51 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
) {
|
||||
// Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
|
||||
// some modifications due to that being in typeck and this being in infer.
|
||||
if let ObligationCauseCode::Pattern { .. } = cause.code() {
|
||||
if let ty::Adt(expected_adt, args) = exp_found.expected.kind() {
|
||||
let compatible_variants: Vec<_> = expected_adt
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|variant| {
|
||||
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.single_field();
|
||||
let sole_field_ty = sole_field.ty(self.tcx, args);
|
||||
if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
|
||||
let variant_path =
|
||||
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
|
||||
// FIXME #56861: DRYer prelude filtering
|
||||
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
|
||||
if let Some((_, path)) = path.split_once("::") {
|
||||
return Some(path.to_string());
|
||||
}
|
||||
}
|
||||
Some(variant_path)
|
||||
} else {
|
||||
None
|
||||
if let ObligationCauseCode::Pattern { .. } = cause.code()
|
||||
&& let ty::Adt(expected_adt, args) = exp_found.expected.kind()
|
||||
{
|
||||
let compatible_variants: Vec<_> = expected_adt
|
||||
.variants()
|
||||
.iter()
|
||||
.filter(|variant| {
|
||||
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
|
||||
})
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.single_field();
|
||||
let sole_field_ty = sole_field.ty(self.tcx, args);
|
||||
if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
|
||||
let variant_path =
|
||||
with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
|
||||
// FIXME #56861: DRYer prelude filtering
|
||||
if let Some(path) = variant_path.strip_prefix("std::prelude::")
|
||||
&& let Some((_, path)) = path.split_once("::")
|
||||
{
|
||||
return Some(path.to_string());
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
match &compatible_variants[..] {
|
||||
[] => {}
|
||||
[variant] => {
|
||||
let sugg = SuggestTuplePatternOne {
|
||||
variant: variant.to_owned(),
|
||||
span_low: cause.span.shrink_to_lo(),
|
||||
span_high: cause.span.shrink_to_hi(),
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
}
|
||||
_ => {
|
||||
// More than one matching variant.
|
||||
let sugg = SuggestTuplePatternMany {
|
||||
path: self.tcx.def_path_str(expected_adt.did()),
|
||||
cause_span: cause.span,
|
||||
compatible_variants,
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
Some(variant_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
match &compatible_variants[..] {
|
||||
[] => {}
|
||||
[variant] => {
|
||||
let sugg = SuggestTuplePatternOne {
|
||||
variant: variant.to_owned(),
|
||||
span_low: cause.span.shrink_to_lo(),
|
||||
span_high: cause.span.shrink_to_hi(),
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
}
|
||||
_ => {
|
||||
// More than one matching variant.
|
||||
let sugg = SuggestTuplePatternMany {
|
||||
path: self.tcx.def_path_str(expected_adt.did()),
|
||||
cause_span: cause.span,
|
||||
compatible_variants,
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -288,19 +288,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
|
||||
.map(|field| (field.name, field.ty(self.tcx, expected_args)))
|
||||
.find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
|
||||
&& let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code()
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
{
|
||||
if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
let suggestion = if expected_def.is_struct() {
|
||||
SuggestAccessingField::Safe { span, snippet, name, ty }
|
||||
} else if expected_def.is_union() {
|
||||
SuggestAccessingField::Unsafe { span, snippet, name, ty }
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
diag.subdiagnostic(suggestion);
|
||||
}
|
||||
}
|
||||
let suggestion = if expected_def.is_struct() {
|
||||
SuggestAccessingField::Safe { span, snippet, name, ty }
|
||||
} else if expected_def.is_union() {
|
||||
SuggestAccessingField::Unsafe { span, snippet, name, ty }
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
diag.subdiagnostic(suggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -540,38 +538,35 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
) -> Option<SuggestAsRefKind> {
|
||||
if let (ty::Adt(exp_def, exp_args), ty::Ref(_, found_ty, _)) =
|
||||
(expected.kind(), found.kind())
|
||||
&& let ty::Adt(found_def, found_args) = *found_ty.kind()
|
||||
{
|
||||
if let ty::Adt(found_def, found_args) = *found_ty.kind() {
|
||||
if exp_def == &found_def {
|
||||
let have_as_ref = &[
|
||||
(sym::Option, SuggestAsRefKind::Option),
|
||||
(sym::Result, SuggestAsRefKind::Result),
|
||||
];
|
||||
if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
|
||||
self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
|
||||
}) {
|
||||
let mut show_suggestion = true;
|
||||
for (exp_ty, found_ty) in
|
||||
std::iter::zip(exp_args.types(), found_args.types())
|
||||
{
|
||||
match *exp_ty.kind() {
|
||||
ty::Ref(_, exp_ty, _) => {
|
||||
match (exp_ty.kind(), found_ty.kind()) {
|
||||
(_, ty::Param(_))
|
||||
| (_, ty::Infer(_))
|
||||
| (ty::Param(_), _)
|
||||
| (ty::Infer(_), _) => {}
|
||||
_ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
|
||||
_ => show_suggestion = false,
|
||||
};
|
||||
}
|
||||
ty::Param(_) | ty::Infer(_) => {}
|
||||
_ => show_suggestion = false,
|
||||
if exp_def == &found_def {
|
||||
let have_as_ref = &[
|
||||
(sym::Option, SuggestAsRefKind::Option),
|
||||
(sym::Result, SuggestAsRefKind::Result),
|
||||
];
|
||||
if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
|
||||
self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
|
||||
}) {
|
||||
let mut show_suggestion = true;
|
||||
for (exp_ty, found_ty) in std::iter::zip(exp_args.types(), found_args.types()) {
|
||||
match *exp_ty.kind() {
|
||||
ty::Ref(_, exp_ty, _) => {
|
||||
match (exp_ty.kind(), found_ty.kind()) {
|
||||
(_, ty::Param(_))
|
||||
| (_, ty::Infer(_))
|
||||
| (ty::Param(_), _)
|
||||
| (ty::Infer(_), _) => {}
|
||||
_ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
|
||||
_ => show_suggestion = false,
|
||||
};
|
||||
}
|
||||
ty::Param(_) | ty::Infer(_) => {}
|
||||
_ => show_suggestion = false,
|
||||
}
|
||||
if show_suggestion {
|
||||
return Some(*msg);
|
||||
}
|
||||
}
|
||||
if show_suggestion {
|
||||
return Some(*msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,15 +381,15 @@ impl IgnoredDiagnosticOption {
|
|||
old: Option<Span>,
|
||||
option_name: &'static str,
|
||||
) {
|
||||
if let (Some(new_item), Some(old_item)) = (new, old) {
|
||||
if let Some(item_def_id) = item_def_id.as_local() {
|
||||
tcx.emit_node_span_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
tcx.local_def_id_to_hir_id(item_def_id),
|
||||
new_item,
|
||||
IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
|
||||
);
|
||||
}
|
||||
if let (Some(new_item), Some(old_item)) = (new, old)
|
||||
&& let Some(item_def_id) = item_def_id.as_local()
|
||||
{
|
||||
tcx.emit_node_span_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
tcx.local_def_id_to_hir_id(item_def_id),
|
||||
new_item,
|
||||
IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2213,26 +2213,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
span: Span,
|
||||
trait_ref: DefId,
|
||||
) {
|
||||
if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
|
||||
if let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind {
|
||||
err.note(format!(
|
||||
"{}s cannot be accessed directly on a `trait`, they can only be \
|
||||
if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id)
|
||||
&& let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind
|
||||
{
|
||||
err.note(format!(
|
||||
"{}s cannot be accessed directly on a `trait`, they can only be \
|
||||
accessed through a specific `impl`",
|
||||
self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
|
||||
));
|
||||
self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
|
||||
));
|
||||
|
||||
if !assoc_item.is_impl_trait_in_trait() {
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"use the fully qualified path to an implementation",
|
||||
format!(
|
||||
"<Type as {}>::{}",
|
||||
self.tcx.def_path_str(trait_ref),
|
||||
assoc_item.name()
|
||||
),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
if !assoc_item.is_impl_trait_in_trait() {
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"use the fully qualified path to an implementation",
|
||||
format!(
|
||||
"<Type as {}>::{}",
|
||||
self.tcx.def_path_str(trait_ref),
|
||||
assoc_item.name()
|
||||
),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -695,15 +695,14 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
|||
source: CandidateSource::Impl(def_id),
|
||||
result: Ok(_),
|
||||
} = cand.kind()
|
||||
&& let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id)
|
||||
{
|
||||
if let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) {
|
||||
let message = infcx
|
||||
.tcx
|
||||
.get_attr(def_id, sym::rustc_reservation_impl)
|
||||
.and_then(|a| a.value_str());
|
||||
if let Some(message) = message {
|
||||
self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message });
|
||||
}
|
||||
let message = infcx
|
||||
.tcx
|
||||
.get_attr(def_id, sym::rustc_reservation_impl)
|
||||
.and_then(|a| a.value_str());
|
||||
if let Some(message) = message {
|
||||
self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -781,16 +781,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self,
|
||||
&project_obligation,
|
||||
)
|
||||
{
|
||||
if let Some(cached_res) = self
|
||||
&& let Some(cached_res) = self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.projection_cache()
|
||||
.is_complete(key)
|
||||
{
|
||||
break 'compute_res Ok(cached_res);
|
||||
}
|
||||
{
|
||||
break 'compute_res Ok(cached_res);
|
||||
}
|
||||
|
||||
// Need to explicitly set the depth of nested goals here as
|
||||
|
|
@ -1436,24 +1434,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
|
||||
let tcx = self.tcx();
|
||||
// Treat reservation impls as ambiguity.
|
||||
if let ImplCandidate(def_id) = candidate {
|
||||
if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) {
|
||||
if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes {
|
||||
let message = tcx
|
||||
.get_attr(def_id, sym::rustc_reservation_impl)
|
||||
.and_then(|a| a.value_str());
|
||||
if let Some(message) = message {
|
||||
debug!(
|
||||
"filter_reservation_impls: \
|
||||
if let ImplCandidate(def_id) = candidate
|
||||
&& let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id)
|
||||
{
|
||||
if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes {
|
||||
let message =
|
||||
tcx.get_attr(def_id, sym::rustc_reservation_impl).and_then(|a| a.value_str());
|
||||
if let Some(message) = message {
|
||||
debug!(
|
||||
"filter_reservation_impls: \
|
||||
reservation impl ambiguity on {:?}",
|
||||
def_id
|
||||
);
|
||||
intercrate_ambiguity_clauses
|
||||
.insert(IntercrateAmbiguityCause::ReservationImpl { message });
|
||||
}
|
||||
def_id
|
||||
);
|
||||
intercrate_ambiguity_clauses
|
||||
.insert(IntercrateAmbiguityCause::ReservationImpl { message });
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(candidate))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -642,11 +642,11 @@ fn fn_abi_adjust_for_abi<'tcx>(
|
|||
// The `deduced_param_attrs` list could be empty if this is a type of function
|
||||
// we can't deduce any parameters for, so make sure the argument index is in
|
||||
// bounds.
|
||||
if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx) {
|
||||
if deduced_param_attrs.read_only {
|
||||
attrs.regular.insert(ArgAttribute::ReadOnly);
|
||||
debug!("added deduced read-only attribute");
|
||||
}
|
||||
if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx)
|
||||
&& deduced_param_attrs.read_only
|
||||
{
|
||||
attrs.regular.insert(ArgAttribute::ReadOnly);
|
||||
debug!("added deduced read-only attribute");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ fn adt_sizedness_constraint<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
(def_id, sizedness): (DefId, SizedTraitKind),
|
||||
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
if let ty::Representability::Infinite(_) = tcx.representability(def_id) {
|
||||
return None;
|
||||
}
|
||||
if let Some(def_id) = def_id.as_local()
|
||||
&& let ty::Representability::Infinite(_) = tcx.representability(def_id)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let def = tcx.adt_def(def_id);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue