Auto merge of #110458 - matthiaskrgr:rollup-1xcxmgc, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #104055 (Migrate diagnostics in `rustc_borrowck`)
 - #110257 (fix false positives for `unused_parens` around unary and binary operations)
 - #110313 (allow `repr(align = x)` on inherent methods)
 - #110337 (Correct default value for default-linker-libraries)
 - #110386 (Clean up traversal macros)
 - #110394 (Various minor Idx-related tweaks)
 - #110425 (Encode def span for `ConstParam`)
 - #110434 (Check freeze with right param-env in `deduced_param_attrs`)
 - #110455 (tests: adapt for LLVM change 5b386b864c7619897c51a1da97d78f1cf6f3eff6)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-17 16:39:01 +00:00
commit 31656e7295
50 changed files with 970 additions and 566 deletions

View File

@ -461,8 +461,8 @@ pub trait LayoutCalculator {
let all_indices = variants.indices();
let needs_disc =
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
let count = niche_variants.size_hint().1.unwrap() as u128;
@ -560,8 +560,7 @@ pub trait LayoutCalculator {
tag: niche_scalar,
tag_encoding: TagEncoding::Niche {
untagged_variant: largest_variant_index,
niche_variants: (VariantIdx::new(*niche_variants.start())
..=VariantIdx::new(*niche_variants.end())),
niche_variants,
niche_start,
},
tag_field: 0,

View File

@ -11,7 +11,7 @@ use bitflags::bitflags;
use rustc_data_structures::intern::Interned;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
use rustc_index::vec::{IndexSlice, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic;
#[cfg(feature = "nightly")]

View File

@ -9,14 +9,14 @@ rustc_index::newtype_index! {
///
/// [`DefId`]: rustc_span::def_id::DefId
#[debug_format = "NodeId({})"]
pub struct NodeId {}
pub struct NodeId {
/// The [`NodeId`] used to represent the root of the crate.
const CRATE_NODE_ID = 0;
}
}
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
/// The [`NodeId`] used to represent the root of the crate.
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
/// When parsing and at the beginning of doing expansions, we initially give all AST nodes
/// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them
/// to have small, positive IDs.

View File

@ -56,18 +56,6 @@ borrowck_returned_lifetime_short =
borrowck_used_impl_require_static =
the used `impl` has a `'static` requirement
borrowck_capture_kind_label =
capture is {$kind_desc} because of use here
borrowck_var_borrow_by_use_place_in_generator =
borrow occurs due to use of {$place} in closure in generator
borrowck_var_borrow_by_use_place_in_closure =
borrow occurs due to use of {$place} in closure
borrowck_var_borrow_by_use_place =
borrow occurs due to use of {$place}
borrowck_borrow_due_to_use_generator =
borrow occurs due to use in generator
@ -101,12 +89,63 @@ borrowck_capture_mut =
borrowck_capture_move =
capture is moved because of use here
borrowck_var_borrow_by_use_place_in_generator =
{$is_single_var ->
*[true] borrow occurs
[false] borrows occur
} due to use of {$place} in generator
borrowck_var_borrow_by_use_place_in_closure =
{$is_single_var ->
*[true] borrow occurs
[false] borrows occur
} due to use of {$place} in closure
borrowck_var_borrow_by_use_in_generator =
borrow occurs due to use in generator
borrowck_var_borrow_by_use_in_closure =
borrow occurs due to use in closure
borrowck_var_move_by_use_place_in_generator =
move occurs due to use of {$place} in generator
borrowck_var_move_by_use_place_in_closure =
move occurs due to use of {$place} in closure
borrowck_var_move_by_use_in_generator =
move occurs due to use in generator
borrowck_var_move_by_use_in_closure =
move occurs due to use in closure
borrowck_partial_var_move_by_use_in_generator =
variable {$is_partial ->
[true] partially moved
*[false] moved
} due to use in generator
borrowck_partial_var_move_by_use_in_closure =
variable {$is_partial ->
[true] partially moved
*[false] moved
} due to use in closure
borrowck_var_first_borrow_by_use_place_in_generator =
first borrow occurs due to use of {$place} in generator
borrowck_var_first_borrow_by_use_place_in_closure =
first borrow occurs due to use of {$place} in closure
borrowck_var_second_borrow_by_use_place_in_generator =
second borrow occurs due to use of {$place} in generator
borrowck_var_second_borrow_by_use_place_in_closure =
second borrow occurs due to use of {$place} in closure
borrowck_var_mutable_borrow_by_use_place_in_closure =
mutable borrow occurs due to use of {$place} in closure
borrowck_cannot_move_when_borrowed =
cannot move out of {$place ->
[value] value
@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param =
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
*[other] this generic parameter must be used with a generic {$kind} parameter
}
borrowck_moved_due_to_call =
{$place_name} {$is_partial ->
[true] partially moved
*[false] moved
} due to this {$is_loop_message ->
[true] call, in previous iteration of loop
*[false] call
}
borrowck_moved_due_to_usage_in_operator =
{$place_name} {$is_partial ->
[true] partially moved
*[false] moved
} due to usage in {$is_loop_message ->
[true] operator, in previous iteration of loop
*[false] operator
}
borrowck_moved_due_to_implicit_into_iter_call =
{$place_name} {$is_partial ->
[true] partially moved
*[false] moved
} due to this implicit call to {$is_loop_message ->
[true] `.into_iter()`, in previous iteration of loop
*[false] `.into_iter()`
}
borrowck_moved_due_to_method_call =
{$place_name} {$is_partial ->
[true] partially moved
*[false] moved
} due to this method {$is_loop_message ->
[true] call, in previous iteration of loop
*[false] call
}
borrowck_value_moved_here =
value {$is_partial ->
[true] partially moved
*[false] moved
} {$is_move_msg ->
[true] into closure here
*[false] here
}{$is_loop_message ->
[true] , in previous iteration of loop
*[false] {""}
}
borrowck_consider_borrow_type_contents =
help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
borrowck_moved_a_fn_once_in_call =
this value implements `FnOnce`, which causes it to be moved when called
borrowck_calling_operator_moves_lhs =
calling this operator moves the left-hand side
borrowck_func_take_self_moved_place =
`{$func}` takes ownership of the receiver `self`, which moves {$place_name}
borrowck_suggest_iterate_over_slice =
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
borrowck_suggest_create_freash_reborrow =
consider reborrowing the `Pin` instead of moving it
borrowck_value_capture_here =
value captured {$is_within ->
[true] here by generator
*[false] here
}
borrowck_move_out_place_here =
{$place} is moved here
borrowck_closure_invoked_twice =
closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
borrowck_closure_moved_twice =
closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
borrowck_ty_no_impl_copy =
{$is_partial_move ->
[true] partial move
*[false] move
} occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait

View File

@ -30,8 +30,8 @@ use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
use crate::diagnostics::find_all_local_uses;
use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
let move_span = move_spans.args_or_use();
let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
let is_move_msg = move_spans.for_closure();
let loop_message = if location == move_out.source || move_site.traversed_back_edge {
", in previous iteration of loop"
} else {
""
};
let is_loop_message = location == move_out.source || move_site.traversed_back_edge;
if location == move_out.source {
is_loop_move = true;
@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
let msg_opt = CapturedMessageOpt {
is_partial_move,
is_loop_message,
is_move_msg,
is_loop_move,
maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
.is_empty(),
};
self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
partially_str,
loop_message,
move_msg,
is_loop_move,
maybe_reinitialized_locations.is_empty(),
msg_opt,
);
}
seen_spans.insert(move_span);
@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
if needs_note {
let span = if let Some(local) = place.as_local() {
Some(self.body.local_decls[local].source_info.span)
if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span;
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move,
ty,
place: &note_msg,
span,
});
} else {
None
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
is_partial_move,
ty,
place: &note_msg,
});
};
self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
}
if let UseSpans::FnSelfUse {
@ -827,11 +836,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
move_spans.var_span_label(
&mut err,
format!("move occurs due to use{}", move_spans.describe()),
"moved",
);
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => MoveUseInGenerator { var_span },
None => MoveUseInClosure { var_span },
}
});
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
@ -868,13 +879,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_span,
&self.describe_any_place(borrow.borrowed_place.as_ref()),
);
borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
let place = &borrow.borrowed_place;
let desc_place = self.describe_any_place(place.as_ref());
match kind {
Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
None => BorrowUsePlaceClosure { place: desc_place, var_span },
Some(_) => {
BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
}
None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
}
});
@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
immutable_section_description,
"mutably borrow",
);
borrow_spans.var_span_label(
borrow_spans.var_subdiag(
None,
&mut err,
format!(
"borrow occurs due to use of {}{}",
desc_place,
borrow_spans.describe(),
),
"immutable",
Some(BorrowKind::Unique),
|kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => BorrowUsePlaceGenerator {
place: desc_place,
var_span,
is_single_var: true,
},
None => BorrowUsePlaceClosure {
place: desc_place,
var_span,
is_single_var: true,
},
}
},
);
return err;
} else {
first_borrow_desc = "immutable ";
@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
};
if issued_spans == borrow_spans {
borrow_spans.var_span_label(
&mut err,
format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),),
gen_borrow_kind.describe_mutability(),
);
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => BorrowUsePlaceGenerator {
place: desc_place,
var_span,
is_single_var: false,
},
None => {
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
}
}
});
} else {
let borrow_place = &issued_borrow.borrowed_place;
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
issued_spans.var_span_label(
issued_spans.var_subdiag(
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
&mut err,
format!(
"first borrow occurs due to use of {}{}",
borrow_place_desc,
issued_spans.describe(),
),
issued_borrow.kind.describe_mutability(),
Some(issued_borrow.kind),
|kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
let borrow_place = &issued_borrow.borrowed_place;
let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
match kind {
Some(_) => {
FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
}
None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
}
},
);
borrow_spans.var_span_label(
borrow_spans.var_subdiag(
Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
&mut err,
format!(
"second borrow occurs due to use of {}{}",
desc_place,
borrow_spans.describe(),
),
gen_borrow_kind.describe_mutability(),
Some(gen_borrow_kind),
|kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
}
},
);
}
@ -1731,9 +1770,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
borrow_spans.args_subdiag(&mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_generator(),
args_span,
}
});
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
@ -1947,9 +1989,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None,
);
let within = if borrow_spans.for_generator() { " by generator" } else { "" };
borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
borrow_spans.args_subdiag(&mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_generator(),
args_span,
}
});
err
}
@ -2382,11 +2427,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
section,
"assign",
);
loan_spans.var_span_label(
&mut err,
format!("borrow occurs due to use{}", loan_spans.describe()),
loan.kind.describe_mutability(),
);
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => BorrowUseInGenerator { var_span },
None => BorrowUseInClosure { var_span },
}
});
self.buffer_error(err);
@ -2396,11 +2444,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
loan_spans.var_span_label(
&mut err,
format!("borrow occurs due to use{}", loan_spans.describe()),
loan.kind.describe_mutability(),
);
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
Some(_) => BorrowUseInGenerator { var_span },
None => BorrowUseInClosure { var_span },
}
});
self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
self.infcx.tcx,

View File

@ -1,5 +1,9 @@
//! Borrow checker diagnostics.
use crate::session_diagnostics::{
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
};
use itertools::Itertools;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
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.span_note(
*span,
&format!(
"closure cannot be invoked more than once because it moves the \
variable `{}` out of its environment",
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
diag.eager_subdiagnostic(
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
OnClosureNote::InvokedTwice {
place_name: &ty::place_to_string_for_capture(
self.infcx.tcx,
hir_place,
),
span: *span,
},
);
return true;
}
@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
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.span_note(
*span,
&format!(
"closure cannot be moved more than once as it is not `Copy` due to \
moving the variable `{}` out of its environment",
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
diag.eager_subdiagnostic(
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
OnClosureNote::MovedTwice {
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
span: *span,
},
);
return true;
}
@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
/// Add a note that a type does not implement `Copy`
pub(super) fn note_type_does_not_implement_copy(
&self,
err: &mut Diagnostic,
place_desc: &str,
ty: Ty<'tcx>,
span: Option<Span>,
move_prefix: &str,
) {
let message = format!(
"{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
);
if let Some(span) = span {
err.span_label(span, message);
} else {
err.note(&message);
}
}
pub(super) fn borrowed_content_source(
&self,
deref_base: PlaceRef<'tcx>,
@ -582,9 +568,13 @@ impl UseSpans<'_> {
}
/// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
pub(super) fn args_subdiag(
self,
err: &mut Diagnostic,
f: impl FnOnce(Span) -> CaptureArgLabel,
) {
if let UseSpans::ClosureUse { args_span, .. } = self {
err.span_label(args_span, message);
err.subdiagnostic(f(args_span));
}
}
@ -595,8 +585,8 @@ impl UseSpans<'_> {
err: &mut Diagnostic,
action: crate::InitializationRequiringAction,
) {
use crate::session_diagnostics::CaptureVarPathUseCause::*;
use crate::InitializationRequiringAction::*;
use CaptureVarPathUseCause::*;
if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
match generator_kind {
Some(_) => {
@ -619,34 +609,14 @@ impl UseSpans<'_> {
}
}
/// Add a span label to the use of the captured variable, if it exists.
pub(super) fn var_span_label(
self,
err: &mut Diagnostic,
message: impl Into<String>,
kind_desc: impl Into<String>,
) {
if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
if capture_kind_span == path_span {
err.span_label(capture_kind_span, message);
} else {
let capture_kind_label =
format!("capture is {} because of use here", kind_desc.into());
let path_label = message;
err.span_label(capture_kind_span, capture_kind_label);
err.span_label(path_span, path_label);
}
}
}
/// Add a subdiagnostic to the use of the captured variable, if it exists.
pub(super) fn var_subdiag(
self,
handler: Option<&rustc_errors::Handler>,
err: &mut Diagnostic,
kind: Option<rustc_middle::mir::BorrowKind>,
f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
) {
use crate::session_diagnostics::CaptureVarKind::*;
if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
if capture_kind_span != path_span {
err.subdiagnostic(match kind {
@ -654,17 +624,21 @@ impl UseSpans<'_> {
rustc_middle::mir::BorrowKind::Shared
| rustc_middle::mir::BorrowKind::Shallow
| rustc_middle::mir::BorrowKind::Unique => {
Immute { kind_span: capture_kind_span }
CaptureVarKind::Immut { kind_span: capture_kind_span }
}
rustc_middle::mir::BorrowKind::Mut { .. } => {
Mut { kind_span: capture_kind_span }
CaptureVarKind::Mut { kind_span: capture_kind_span }
}
},
None => Move { kind_span: capture_kind_span },
None => CaptureVarKind::Move { kind_span: capture_kind_span },
});
};
err.subdiagnostic(f(generator_kind, path_span));
let diag = f(generator_kind, path_span);
match handler {
Some(hd) => err.eager_subdiagnostic(hd, diag),
None => err.subdiagnostic(diag),
};
}
}
@ -684,20 +658,6 @@ impl UseSpans<'_> {
}
}
/// Describe the span associated with a use of a place.
pub(super) fn describe(&self) -> &str {
match *self {
UseSpans::ClosureUse { generator_kind, .. } => {
if generator_kind.is_some() {
" in generator"
} else {
" in closure"
}
}
_ => "",
}
}
pub(super) fn or_else<F>(self, if_other: F) -> Self
where
F: FnOnce() -> Self,
@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> {
}
}
///helper struct for explain_captures()
struct CapturedMessageOpt {
is_partial_move: bool,
is_loop_message: bool,
is_move_msg: bool,
is_loop_move: bool,
maybe_reinitialized_locations_is_empty: bool,
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span: Span,
move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>,
partially_str: &str,
loop_message: &str,
move_msg: &str,
is_loop_move: bool,
maybe_reinitialized_locations_is_empty: bool,
msg_opt: CapturedMessageOpt,
) {
let CapturedMessageOpt {
is_partial_move: is_partial,
is_loop_message,
is_move_msg,
is_loop_move,
maybe_reinitialized_locations_is_empty,
} = msg_opt;
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
let place_name = self
.describe_place(moved_place.as_ref())
@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.span_label(
err.subdiagnostic(CaptureReasonLabel::Call {
fn_call_span,
&format!(
"{place_name} {partially_str}moved due to this call{loop_message}",
),
);
err.span_note(
var_span,
"this value implements `FnOnce`, which causes it to be moved when called",
);
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
}
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
err.span_label(
err.subdiagnostic(CaptureReasonLabel::OperatorUse {
fn_call_span,
&format!(
"{place_name} {partially_str}moved due to usage in operator{loop_message}",
),
);
place_name: &place_name,
is_partial,
is_loop_message,
});
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
self_arg.span,
"calling this operator moves the left-hand side",
);
err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
span: self_arg.span,
});
}
}
CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
@ -1086,23 +1054,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => false,
};
if suggest {
err.span_suggestion_verbose(
move_span.shrink_to_lo(),
&format!(
"consider iterating over a slice of the `{ty}`'s content to \
avoid moving into the `for` loop",
),
"&",
Applicability::MaybeIncorrect,
);
err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
ty,
span: move_span.shrink_to_lo(),
});
}
err.span_label(
err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
fn_call_span,
&format!(
"{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
),
);
place_name: &place_name,
is_partial,
is_loop_message,
});
// If the moved place was a `&mut` ref, then we can
// suggest to reborrow it where it was moved, so it
// will still be valid by the time we get to the usage.
@ -1125,13 +1088,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
} else {
err.span_label(
err.subdiagnostic(CaptureReasonLabel::MethodCall {
fn_call_span,
&format!(
"{place_name} {partially_str}moved due to this method call{loop_message}",
),
);
place_name: &place_name,
is_partial,
is_loop_message,
});
let infcx = tcx.infer_ctxt().build();
// Erase and shadow everything that could be passed to the new infcx.
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
@ -1147,12 +1109,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
)
&& infcx.can_eq(self.param_env, ty, self_ty)
{
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
"consider reborrowing the `Pin` instead of moving it",
"as_mut().".to_string(),
Applicability::MaybeIncorrect,
);
err.eager_subdiagnostic(
&self.infcx.tcx.sess.parse_sess.span_diagnostic,
CaptureReasonSuggest::FreshReborrow {
span: fn_call_span.shrink_to_lo(),
});
}
if let Some(clone_trait) = tcx.lang_items().clone_trait()
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
@ -1177,10 +1138,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
let func = tcx.def_path_str(method_did);
err.span_note(
self_arg.span,
&format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
);
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
func,
place_name,
span: self_arg.span,
});
}
let parent_did = tcx.parent(method_did);
let parent_self_ty =
@ -1194,30 +1156,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.span_label(
var_span,
"help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
);
err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
}
}
// Other desugarings takes &self, which cannot cause a move
_ => {}
}
} else {
if move_span != span || !loop_message.is_empty() {
err.span_label(
if move_span != span || is_loop_message {
err.subdiagnostic(CaptureReasonLabel::MovedHere {
move_span,
format!("value {partially_str}moved{move_msg} here{loop_message}"),
);
is_partial,
is_move_msg,
is_loop_message,
});
}
// If the move error occurs due to a loop, don't show
// another message for the same span
if loop_message.is_empty() {
move_spans.var_span_label(
err,
format!("variable {partially_str}moved due to use{}", move_spans.describe()),
"moved",
);
if !is_loop_message {
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
})
}
}
}

View File

@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{
};
use rustc_span::{BytePos, Span};
use crate::diagnostics::CapturedMessageOpt;
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
};
let msg_opt = CapturedMessageOpt {
is_partial_move: false,
is_loop_message: false,
is_move_msg: false,
is_loop_move: false,
maybe_reinitialized_locations_is_empty: true,
};
if let Some(use_spans) = use_spans {
self.explain_captures(
&mut err, span, span, use_spans, move_place, "", "", "", false, true,
);
self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt);
}
err
}
@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
None => "value".to_string(),
};
self.note_type_does_not_implement_copy(
err,
&place_desc,
place_ty,
Some(span),
"",
);
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
});
} else {
binds_to.sort();
binds_to.dedup();
@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Some(desc) => format!("`{desc}`"),
None => "value".to_string(),
};
self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
});
use_spans.args_span_label(err, format!("{place_desc} is moved here"));
use_spans.args_subdiag(err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
place: place_desc,
args_span,
}
});
}
}
}
@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
if binds_to.len() == 1 {
self.note_type_does_not_implement_copy(
err,
&format!("`{}`", self.local_names[*local].unwrap()),
bind_to.ty,
Some(binding_span),
"",
);
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: bind_to.ty,
place: &place_desc,
span: binding_span,
});
}
}

View File

@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
if suggest {
borrow_spans.var_span_label(
&mut err,
format!(
"mutable borrow occurs due to use of {} in closure",
self.describe_any_place(access_place.as_ref()),
),
"mutable",
);
borrow_spans.var_subdiag(
None,
&mut err,
Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
|_kind, var_span| {
let place = self.describe_any_place(access_place.as_ref());
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
place,
var_span,
}
},
);
}
borrow_span
}

View File

@ -3,7 +3,7 @@
use crate::region_infer::RegionInferenceContext;
use crate::Upvar;
use rustc_index::vec::{Idx, IndexSlice};
use rustc_index::vec::IndexSlice;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_span::source_map::Span;
@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
argument_index: usize,
) -> (Option<Symbol>, Span) {
let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
let argument_local = Local::new(implicit_inputs + argument_index + 1);
let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
let argument_name = local_names[argument_local];

View File

@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts;
use polonius_engine::Atom;
use rustc_index::vec::Idx;
use rustc_middle::mir::Local;
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MovePathIndex;
@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts {
impl Atom for BorrowIndex {
fn index(self) -> usize {
Idx::index(self)
self.as_usize()
}
}
impl Atom for LocationIndex {
fn index(self) -> usize {
Idx::index(self)
self.as_usize()
}
}

View File

@ -1,6 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_index::vec::{Idx, IndexVec};
use rustc_index::vec::IndexVec;
use rustc_middle::mir::{BasicBlock, Body, Location};
/// Maps between a MIR Location, which identifies a particular
@ -50,19 +50,19 @@ impl LocationTable {
}
pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
(0..self.num_points).map(LocationIndex::new)
(0..self.num_points).map(LocationIndex::from_usize)
}
pub fn start_index(&self, location: Location) -> LocationIndex {
let Location { block, statement_index } = location;
let start_index = self.statements_before_block[block];
LocationIndex::new(start_index + statement_index * 2)
LocationIndex::from_usize(start_index + statement_index * 2)
}
pub fn mid_index(&self, location: Location) -> LocationIndex {
let Location { block, statement_index } = location;
let start_index = self.statements_before_block[block];
LocationIndex::new(start_index + statement_index * 2 + 1)
LocationIndex::from_usize(start_index + statement_index * 2 + 1)
}
pub fn to_location(&self, index: LocationIndex) -> RichLocation {

View File

@ -7,8 +7,8 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexSlice;
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
use rustc_middle::mir::{
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
Promoted,
Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
START_BLOCK,
};
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
use rustc_span::symbol::sym;
@ -94,8 +94,8 @@ fn populate_polonius_move_facts(
}
}
let fn_entry_start = location_table
.start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
let fn_entry_start =
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
// initialized_at
for init in move_data.inits.iter() {

View File

@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause {
#[derive(Subdiagnostic)]
pub(crate) enum CaptureVarKind {
#[label(borrowck_capture_immute)]
Immute {
Immut {
#[primary_span]
kind_span: Span,
},
@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind {
pub(crate) enum CaptureVarCause {
#[label(borrowck_var_borrow_by_use_place_in_generator)]
BorrowUsePlaceGenerator {
is_single_var: bool,
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_borrow_by_use_place_in_closure)]
BorrowUsePlaceClosure {
is_single_var: bool,
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_borrow_by_use_in_generator)]
BorrowUseInGenerator {
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_borrow_by_use_in_closure)]
BorrowUseInClosure {
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_move_by_use_in_generator)]
MoveUseInGenerator {
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_move_by_use_in_closure)]
MoveUseInClosure {
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_first_borrow_by_use_place_in_generator)]
FirstBorrowUsePlaceGenerator {
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_first_borrow_by_use_place_in_closure)]
FirstBorrowUsePlaceClosure {
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_second_borrow_by_use_place_in_generator)]
SecondBorrowUsePlaceGenerator {
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_second_borrow_by_use_place_in_closure)]
SecondBorrowUsePlaceClosure {
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_mutable_borrow_by_use_place_in_closure)]
MutableBorrowUsePlaceClosure {
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_partial_var_move_by_use_in_generator)]
PartialMoveUseInGenerator {
#[primary_span]
var_span: Span,
is_partial: bool,
},
#[label(borrowck_partial_var_move_by_use_in_closure)]
PartialMoveUseInClosure {
#[primary_span]
var_span: Span,
is_partial: bool,
},
}
#[derive(Diagnostic)]
@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
#[label]
pub param_span: Span,
}
#[derive(Subdiagnostic)]
pub(crate) enum CaptureReasonLabel<'a> {
#[label(borrowck_moved_due_to_call)]
Call {
#[primary_span]
fn_call_span: Span,
place_name: &'a str,
is_partial: bool,
is_loop_message: bool,
},
#[label(borrowck_moved_due_to_usage_in_operator)]
OperatorUse {
#[primary_span]
fn_call_span: Span,
place_name: &'a str,
is_partial: bool,
is_loop_message: bool,
},
#[label(borrowck_moved_due_to_implicit_into_iter_call)]
ImplicitCall {
#[primary_span]
fn_call_span: Span,
place_name: &'a str,
is_partial: bool,
is_loop_message: bool,
},
#[label(borrowck_moved_due_to_method_call)]
MethodCall {
#[primary_span]
fn_call_span: Span,
place_name: &'a str,
is_partial: bool,
is_loop_message: bool,
},
#[label(borrowck_value_moved_here)]
MovedHere {
#[primary_span]
move_span: Span,
is_partial: bool,
is_move_msg: bool,
is_loop_message: bool,
},
#[label(borrowck_consider_borrow_type_contents)]
BorrowContent {
#[primary_span]
var_span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum CaptureReasonNote {
#[note(borrowck_moved_a_fn_once_in_call)]
FnOnceMoveInCall {
#[primary_span]
var_span: Span,
},
#[note(borrowck_calling_operator_moves_lhs)]
LhsMoveByOperator {
#[primary_span]
span: Span,
},
#[note(borrowck_func_take_self_moved_place)]
FuncTakeSelf {
func: String,
place_name: String,
#[primary_span]
span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum CaptureReasonSuggest<'tcx> {
#[suggestion(
borrowck_suggest_iterate_over_slice,
applicability = "maybe-incorrect",
code = "&",
style = "verbose"
)]
IterateSlice {
ty: Ty<'tcx>,
#[primary_span]
span: Span,
},
#[suggestion(
borrowck_suggest_create_freash_reborrow,
applicability = "maybe-incorrect",
code = "as_mut().",
style = "verbose"
)]
FreshReborrow {
#[primary_span]
span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum CaptureArgLabel {
#[label(borrowck_value_capture_here)]
Capture {
is_within: bool,
#[primary_span]
args_span: Span,
},
#[label(borrowck_move_out_place_here)]
MoveOutPlace {
place: String,
#[primary_span]
args_span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum OnClosureNote<'a> {
#[note(borrowck_closure_invoked_twice)]
InvokedTwice {
place_name: &'a str,
#[primary_span]
span: Span,
},
#[note(borrowck_closure_moved_twice)]
MovedTwice {
place_name: &'a str,
#[primary_span]
span: Span,
},
}
#[derive(Subdiagnostic)]
pub(crate) enum TypeNoCopy<'a, 'tcx> {
#[label(borrowck_ty_no_impl_copy)]
Label {
is_partial_move: bool,
ty: Ty<'tcx>,
place: &'a str,
#[primary_span]
span: Span,
},
#[note(borrowck_ty_no_impl_copy)]
Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
}

View File

@ -7,7 +7,6 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// In MIR, argument N is stored in local N+1.
let local = Local::new(argument_index + 1);
let local = Local::from_usize(argument_index + 1);
let mir_input_ty = body.local_decls[local].ty;

View File

@ -19,7 +19,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::BodyOwnerKind;
use rustc_index::vec::{Idx, IndexVec};
use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// Returns an iterator over all the RegionVids corresponding to
/// universally quantified free regions.
pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
(FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
}
/// Returns `true` if `r` is classified as an local region.

View File

@ -12,7 +12,6 @@ use crate::MemFlags;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if self.fn_abi.c_variadic {
// The `VaList` "spoofed" argument is just after all the real arguments.
let va_list_arg_idx = self.fn_abi.args.len();
match self.locals[mir::Local::new(1 + va_list_arg_idx)] {
match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] {
LocalRef::Place(va_list) => {
bx.va_end(va_list.llval);
}

View File

@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let variant_index_relative = u32::try_from(variant_index_relative)
.expect("we checked that this fits into a u32");
// Then computing the absolute variant idx should not overflow any more.
let variant_index = variants_start
.checked_add(variant_index_relative)
.expect("overflow computing absolute variant idx");
let variants_len = op
let variant_index = VariantIdx::from_u32(
variants_start
.checked_add(variant_index_relative)
.expect("overflow computing absolute variant idx"),
);
let variants = op
.layout
.ty
.ty_adt_def()
.expect("tagged layout for non adt")
.variants()
.len();
assert!(usize::try_from(variant_index).unwrap() < variants_len);
VariantIdx::from_u32(variant_index)
.variants();
assert!(variant_index < variants.next_index());
variant_index
} else {
untagged_variant
}

View File

@ -17,7 +17,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_target::abi::FieldIdx;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::ObligationCause;
@ -875,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant.fields.len() == 1
})
.filter_map(|variant| {
let sole_field = &variant.fields[FieldIdx::from_u32(0)];
let sole_field = &variant.single_field();
let field_is_local = sole_field.did.is_local();
let field_is_accessible =

View File

@ -4,7 +4,7 @@ use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_target::abi::{FieldIdx, Pointer, VariantIdx};
use rustc_target::abi::{Pointer, VariantIdx};
use super::FnCtxt;
@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
}
if def.variant(data_idx).fields.len() == 1 {
return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs);
return def.variant(data_idx).single_field().ty(tcx, substs);
}
}

View File

@ -10,7 +10,6 @@ use rustc_middle::traits::{
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, BytePos, Span};
use rustc_target::abi::FieldIdx;
use crate::errors::{
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
})
.filter_map(|variant| {
let sole_field = &variant.fields[FieldIdx::from_u32(0)];
let sole_field = &variant.single_field();
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
let variant_path =

View File

@ -569,36 +569,50 @@ trait UnusedDelimLint {
}
}
// Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
let lhs_needs_parens = {
// Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
{
let mut innermost = inner;
loop {
innermost = match &innermost.kind {
ExprKind::Binary(_, lhs, _rhs) => lhs,
ExprKind::Binary(_op, lhs, _rhs) => lhs,
ExprKind::Call(fn_, _params) => fn_,
ExprKind::Cast(expr, _ty) => expr,
ExprKind::Type(expr, _ty) => expr,
ExprKind::Index(base, _subscript) => base,
_ => break false,
_ => break,
};
if !classify::expr_requires_semi_to_be_stmt(innermost) {
break true;
return true;
}
}
};
}
lhs_needs_parens
|| (followed_by_block
&& match &inner.kind {
ExprKind::Ret(_)
| ExprKind::Break(..)
| ExprKind::Yield(..)
| ExprKind::Yeet(..) => true,
ExprKind::Range(_lhs, Some(rhs), _limits) => {
matches!(rhs.kind, ExprKind::Block(..))
}
_ => parser::contains_exterior_struct_lit(&inner),
})
// Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`.
if !followed_by_block {
return false;
}
let mut innermost = inner;
loop {
innermost = match &innermost.kind {
ExprKind::Unary(_op, expr) => expr,
ExprKind::Binary(_op, _lhs, rhs) => rhs,
ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
ExprKind::Assign(_lhs, rhs, _span) => rhs,
ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
ExprKind::Break(_label, None) => return false,
ExprKind::Break(_label, Some(break_expr)) => {
return matches!(break_expr.kind, ExprKind::Block(..));
}
ExprKind::Range(_lhs, Some(rhs), _limits) => {
return matches!(rhs.kind, ExprKind::Block(..));
}
_ => return parser::contains_exterior_struct_lit(&inner),
}
}
}
fn emit_unused_delims_expr(

View File

@ -823,6 +823,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::TyParam
| DefKind::ConstParam
| DefKind::Fn
| DefKind::Const
| DefKind::Static(_)
@ -837,8 +838,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::Impl { .. }
| DefKind::Closure
| DefKind::Generator => true,
DefKind::ConstParam
| DefKind::ExternCrate
DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::ImplTraitPlaceholder

View File

@ -392,10 +392,8 @@ pub type QueryOutlivesConstraint<'tcx> =
(ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
TrivialTypeTraversalAndLiftImpls! {
for <'tcx> {
crate::infer::canonical::Certainty,
crate::infer::canonical::CanonicalTyVarKind,
}
crate::infer::canonical::Certainty,
crate::infer::canonical::CanonicalTyVarKind,
}
impl<'tcx> CanonicalVarValues<'tcx> {

View File

@ -43,34 +43,26 @@ macro_rules! span_bug {
#[macro_export]
macro_rules! CloneLiftImpls {
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
($($ty:ty,)+) => {
$(
impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
impl<'tcx> $crate::ty::Lift<'tcx> for $ty {
type Lifted = Self;
fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
Some(self)
}
}
)+
};
($($ty:ty,)+) => {
CloneLiftImpls! {
for <'tcx> {
$($ty,)+
}
}
};
}
/// Used for types that are `Copy` and which **do not care arena
/// allocated data** (i.e., don't need to be folded).
#[macro_export]
macro_rules! TrivialTypeTraversalImpls {
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
($($ty:ty,)+) => {
$(
impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty {
fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>(
self,
_: &mut F,
) -> ::std::result::Result<Self, F::Error> {
@ -78,7 +70,7 @@ macro_rules! TrivialTypeTraversalImpls {
}
#[inline]
fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<'tcx>>>(
self,
_: &mut F,
) -> Self {
@ -86,9 +78,9 @@ macro_rules! TrivialTypeTraversalImpls {
}
}
impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty {
#[inline]
fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
&self,
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
@ -98,14 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
}
)+
};
($($ty:ty,)+) => {
TrivialTypeTraversalImpls! {
for<'tcx> {
$($ty,)+
}
}
};
}
#[macro_export]

View File

@ -714,9 +714,7 @@ pub enum BindingForm<'tcx> {
}
TrivialTypeTraversalAndLiftImpls! {
for<'tcx> {
BindingForm<'tcx>,
}
BindingForm<'tcx>,
}
mod binding_form_impl {

View File

@ -25,9 +25,7 @@ TrivialTypeTraversalAndLiftImpls! {
}
TrivialTypeTraversalImpls! {
for <'tcx> {
ConstValue<'tcx>,
}
ConstValue<'tcx>,
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {

View File

@ -1329,9 +1329,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
// This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
CloneLiftImpls! { for<'tcx> {
Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
} }
CloneLiftImpls! {
Constness,
traits::WellFormedLoc,
ImplPolarity,
crate::mir::ReturnConstraint,
}
macro_rules! sty_debug_print {
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{

View File

@ -1963,6 +1963,16 @@ impl VariantDef {
pub fn ctor_def_id(&self) -> Option<DefId> {
self.ctor.map(|(_, def_id)| def_id)
}
/// Returns the one field in this variant.
///
/// `panic!`s if there are no fields or multiple fields.
#[inline]
pub fn single_field(&self) -> &FieldDef {
assert!(self.fields.len() == 1);
&self.fields[FieldIdx::from_u32(0)]
}
}
impl PartialEq for VariantDef {

View File

@ -276,9 +276,7 @@ TrivialTypeTraversalAndLiftImpls! {
}
TrivialTypeTraversalAndLiftImpls! {
for<'tcx> {
ty::ValTree<'tcx>,
}
ty::ValTree<'tcx>,
}
///////////////////////////////////////////////////////////////////////////

View File

@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
use rustc_session::config::OptLevel;
/// A visitor that determines which arguments have been mutated. We can't use the mutability field
@ -198,11 +198,12 @@ pub fn deduced_param_attrs<'tcx>(
// see [1].
//
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs {
read_only: !deduce_read_only.mutable_args.contains(arg_index)
&& local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
&& local_decl.ty.is_freeze(tcx, param_env),
},
),
);

View File

@ -627,9 +627,9 @@ passes_attr_application_struct_enum_union =
attribute should be applied to a struct, enum, or union
.label = not a struct, enum, or union
passes_attr_application_struct_enum_function_union =
attribute should be applied to a struct, enum, function, or union
.label = not a struct, enum, function, or union
passes_attr_application_struct_enum_function_method_union =
attribute should be applied to a struct, enum, function, associated function, or union
.label = not a struct, enum, function, associated function, or union
passes_transparent_incompatible =
transparent {$target} cannot have other repr hints

View File

@ -1728,7 +1728,9 @@ impl CheckAttrVisitor<'_> {
}
}
sym::align => {
if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
(target, self.tcx.features().fn_align)
{
feature_err(
&self.tcx.sess.parse_sess,
sym::fn_align,
@ -1739,10 +1741,14 @@ impl CheckAttrVisitor<'_> {
}
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
Target::Struct
| Target::Union
| Target::Enum
| Target::Fn
| Target::Method(_) => continue,
_ => {
self.tcx.sess.emit_err(
errors::AttrApplication::StructEnumFunctionUnion {
errors::AttrApplication::StructEnumFunctionMethodUnion {
hint_span: hint.span(),
span,
},

View File

@ -1355,8 +1355,8 @@ pub enum AttrApplication {
#[label]
span: Span,
},
#[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
StructEnumFunctionUnion {
#[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
StructEnumFunctionMethodUnion {
#[primary_span]
hint_span: Span,
#[label]

View File

@ -24,10 +24,7 @@ impl<K: DepKind> DepGraphQuery<K> {
pub fn push(&mut self, index: DepNodeIndex, node: DepNode<K>, edges: &[DepNodeIndex]) {
let source = self.graph.add_node(node);
if index.index() >= self.dep_index_to_index.len() {
self.dep_index_to_index.resize(index.index() + 1, None);
}
self.dep_index_to_index[index] = Some(source);
self.dep_index_to_index.insert(index, source);
self.indices.insert(node, source);
for &target in edges.iter() {

View File

@ -11,12 +11,13 @@
use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
use crate::solve::{CanonicalResponse, QueryResult, Response};
use rustc_index::vec::IndexVec;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use rustc_middle::ty::{self, GenericArgKind};
use rustc_middle::ty::{self, BoundVar, GenericArgKind};
use rustc_span::DUMMY_SP;
use std::iter;
use std::ops::Deref;
@ -139,25 +140,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
//
// We therefore instantiate the existential variable in the canonical response with the
// inference variable of the input right away, which is more performant.
let mut opt_values = vec![None; response.variables.len()];
let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
match result_value.unpack() {
GenericArgKind::Type(t) => {
if let &ty::Bound(debruijn, b) = t.kind() {
assert_eq!(debruijn, ty::INNERMOST);
opt_values[b.var.index()] = Some(*original_value);
opt_values[b.var] = Some(*original_value);
}
}
GenericArgKind::Lifetime(r) => {
if let ty::ReLateBound(debruijn, br) = *r {
assert_eq!(debruijn, ty::INNERMOST);
opt_values[br.var.index()] = Some(*original_value);
opt_values[br.var] = Some(*original_value);
}
}
GenericArgKind::Const(c) => {
if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
assert_eq!(debrujin, ty::INNERMOST);
opt_values[b.index()] = Some(*original_value);
opt_values[b] = Some(*original_value);
}
}
}
@ -180,7 +181,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// more placeholders then they should be able to. However the inference variables have
// to "come from somewhere", so by equating them with the original values of the caller
// later on, we pull them down into their correct universe again.
if let Some(v) = opt_values[index] {
if let Some(v) = opt_values[BoundVar::from_usize(index)] {
v
} else {
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)

View File

@ -33,144 +33,3 @@ macro_rules! TrivialTypeTraversalImpls {
)+
};
}
macro_rules! EnumTypeTraversalImpl {
(impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
$($variants:tt)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s
$(where $($wc)*)*
{
fn try_fold_with<V: $crate::fold::FallibleTypeFolder<$tcx>>(
self,
folder: &mut V,
) -> ::std::result::Result<Self, V::Error> {
EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
}
}
};
(impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
$($variants:tt)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s
$(where $($wc)*)*
{
fn visit_with<V: $crate::visit::TypeVisitor<$tcx>>(
&self,
visitor: &mut V,
) -> ::std::ops::ControlFlow<V::BreakTy> {
EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
}
}
};
(@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
Ok(match $this {
$($output)*
})
};
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
$variant ( $($variant_arg),* ) => {
$variant (
$($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
)
}
$($output)*
)
)
};
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
$variant { $($variant_arg),* } => {
$variant {
$($variant_arg: $crate::fold::TypeFoldable::fold_with(
$variant_arg, $folder
)?),* }
}
$($output)*
)
)
};
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path), $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
$variant => { $variant }
$($output)*
)
)
};
(@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
match $this {
$($output)*
}
};
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant ( $($variant_arg),* ) => {
$($crate::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
::std::ops::ControlFlow::Continue(())
}
$($output)*
)
)
};
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant { $($variant_arg),* } => {
$($crate::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
::std::ops::ControlFlow::Continue(())
}
$($output)*
)
)
};
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path), $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant => { ::std::ops::ControlFlow::Continue(()) }
$($output)*
)
)
};
}

View File

@ -70,30 +70,40 @@ impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>>
}
}
EnumTypeTraversalImpl! {
impl<I, T> TypeFoldable<I> for Option<T> {
(Some)(a),
(None),
} where I: Interner, T: TypeFoldable<I>
}
EnumTypeTraversalImpl! {
impl<I, T> TypeVisitable<I> for Option<T> {
(Some)(a),
(None),
} where I: Interner, T: TypeVisitable<I>
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(match self {
Some(v) => Some(v.try_fold_with(folder)?),
None => None,
})
}
}
EnumTypeTraversalImpl! {
impl<I, T, E> TypeFoldable<I> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>,
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self {
Some(v) => v.visit_with(visitor),
None => ControlFlow::Continue(()),
}
}
}
EnumTypeTraversalImpl! {
impl<I, T, E> TypeVisitable<I> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>,
impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(match self {
Ok(v) => Ok(v.try_fold_with(folder)?),
Err(e) => Err(e.try_fold_with(folder)?),
})
}
}
impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self {
Ok(v) => v.visit_with(visitor),
Err(e) => e.visit_with(visitor),
}
}
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {

View File

@ -84,8 +84,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.
This flag controls whether or not the linker includes its default libraries.
It takes one of the following values:
* `y`, `yes`, `on`, `true` or no value: include default libraries (the default).
* `n`, `no`, `off` or `false`: exclude default libraries.
* `y`, `yes`, `on`, `true`: include default libraries.
* `n`, `no`, `off` or `false` or no value: exclude default libraries (the default).
For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
the linker.

View File

@ -7,3 +7,43 @@
#[no_mangle]
#[repr(align(16))]
pub fn fn_align() {}
pub struct A;
impl A {
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
pub fn method_align(self) {}
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
pub fn associated_fn() {}
}
trait T: Sized {
fn trait_fn() {}
// CHECK: align 32
#[repr(align(32))]
fn trait_method(self) {}
}
impl T for A {
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
fn trait_fn() {}
// CHECK: align 16
#[no_mangle]
#[repr(align(16))]
fn trait_method(self) {}
}
impl T for () {}
pub fn foo() {
().trait_method();
}

View File

@ -20,8 +20,8 @@ thread_local!(static A: Cell<u32> = const { Cell::new(1) });
// CHECK-LABEL: @get
#[no_mangle]
fn get() -> u32 {
// CHECK: %0 = load i32, {{.*}}[[TLS]]{{.*}}
// CHECK-NEXT: ret i32 %0
// CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
// CHECK-NEXT: ret i32 [[RET_0]]
A.with(|a| a.get())
}
@ -36,8 +36,8 @@ fn set(v: u32) {
// CHECK-LABEL: @get_aux
#[no_mangle]
fn get_aux() -> u64 {
// CHECK: %0 = load i64, {{.*}}[[TLS_AUX]]
// CHECK-NEXT: ret i64 %0
// CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
// CHECK-NEXT: ret i64 [[RET_1]]
aux::A.with(|a| a.get())
}

View File

@ -0,0 +1,5 @@
#[repr(align(16))]
//~^ ERROR attribute should be applied to a struct, enum, function, associated function, or union
pub type Foo = i32;
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union
--> $DIR/invalid-repr.rs:1:8
|
LL | #[repr(align(16))]
| ^^^^^^^^^
LL |
LL | pub type Foo = i32;
| ------------------- not a struct, enum, function, associated function, or union
error: aborting due to previous error
For more information about this error, try `rustc --explain E0517`.

View File

@ -0,0 +1,19 @@
// build-pass
// compile-flags: -Copt-level=1 --crate-type=lib
#![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete
pub unsafe trait Storage {
type Handle;
}
pub unsafe trait MultipleStorage: Storage {}
default unsafe impl<S> Storage for S where S: MultipleStorage {}
// Make sure that we call is_freeze on `(S::Handle,)` in the param-env of `ice`,
// instead of in an empty, reveal-all param-env.
pub fn ice<S: Storage>(boxed: (S::Handle,)) -> (S::Handle,) {
boxed
}

View File

@ -0,0 +1,12 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/freeze-on-polymorphic-projection.rs:4:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -0,0 +1 @@
pub fn test<const N: usize, T>() {}

View File

@ -0,0 +1,8 @@
// aux-build: foreign-generic-mismatch-with-const-arg.rs
extern crate foreign_generic_mismatch_with_const_arg;
fn main() {
foreign_generic_mismatch_with_const_arg::test::<1>();
//~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied
}

View File

@ -0,0 +1,21 @@
error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/foreign-generic-mismatch-with-const-arg.rs:6:46
|
LL | foreign_generic_mismatch_with_const_arg::test::<1>();
| ^^^^ - supplied 1 generic argument
| |
| expected 2 generic arguments
|
note: function defined here, with 2 generic parameters: `N`, `T`
--> $DIR/auxiliary/foreign-generic-mismatch-with-const-arg.rs:1:8
|
LL | pub fn test<const N: usize, T>() {}
| ^^^^ -------------- -
help: add missing generic argument
|
LL | foreign_generic_mismatch_with_const_arg::test::<1, T>();
| +++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0107`.

View File

@ -21,17 +21,32 @@ fn lint_on_top_level() {
let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern
}
fn _no_lint_attr() {
fn no_lint_attr() {
let _x = #[allow(dead_code)] (1 + 2);
}
fn _no_lint_yeet() -> Result<(), ()> {
fn no_lint_yeet() -> Result<(), ()> {
#[allow(unreachable_code)]
if (do yeet) {}
Ok(())
}
fn no_lint_ops() {
#![allow(unreachable_code, irrefutable_let_patterns)]
if ((..{}) == ..{}) {}
if (!return) {}
loop { match (() = () = () = break {}) {} }
while let () = (*&mut false |= true && return) {}
}
fn lint_break_if_not_followed_by_block() {
#![allow(unreachable_code)]
loop { if break {} } //~ ERROR unnecessary parentheses
loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses
loop { if (break { println!("hello") }) {} }
}
// Don't lint in these cases (#64106).
fn or_patterns_no_lint() {
match Box::new(0) {

View File

@ -21,17 +21,32 @@ fn lint_on_top_level() {
let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
}
fn _no_lint_attr() {
fn no_lint_attr() {
let _x = #[allow(dead_code)] (1 + 2);
}
fn _no_lint_yeet() -> Result<(), ()> {
fn no_lint_yeet() -> Result<(), ()> {
#[allow(unreachable_code)]
if (do yeet) {}
Ok(())
}
fn no_lint_ops() {
#![allow(unreachable_code, irrefutable_let_patterns)]
if ((..{}) == ..{}) {}
if (!return) {}
loop { match (() = () = () = break {}) {} }
while let () = (*&mut false |= true && return) {}
}
fn lint_break_if_not_followed_by_block() {
#![allow(unreachable_code)]
loop { if (break) {} } //~ ERROR unnecessary parentheses
loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses
loop { if (break { println!("hello") }) {} }
}
// Don't lint in these cases (#64106).
fn or_patterns_no_lint() {
match Box::new(0) {

View File

@ -75,8 +75,32 @@ LL - let _ = |(a): u8| 0;
LL + let _ = |a: u8| 0;
|
error: unnecessary parentheses around `if` condition
--> $DIR/issue-54538-unused-parens-lint.rs:45:15
|
LL | loop { if (break) {} }
| ^ ^
|
help: remove these parentheses
|
LL - loop { if (break) {} }
LL + loop { if break {} }
|
error: unnecessary parentheses around `if` condition
--> $DIR/issue-54538-unused-parens-lint.rs:46:15
|
LL | loop { if (break ({ println!("hello") })) {} }
| ^ ^
|
help: remove these parentheses
|
LL - loop { if (break ({ println!("hello") })) {} }
LL + loop { if break ({ println!("hello") }) {} }
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:56:12
--> $DIR/issue-54538-unused-parens-lint.rs:71:12
|
LL | if let (0 | 1) = 0 {}
| ^ ^
@ -88,7 +112,7 @@ LL + if let 0 | 1 = 0 {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:57:13
--> $DIR/issue-54538-unused-parens-lint.rs:72:13
|
LL | if let ((0 | 1),) = (0,) {}
| ^ ^
@ -100,7 +124,7 @@ LL + if let (0 | 1,) = (0,) {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:58:13
--> $DIR/issue-54538-unused-parens-lint.rs:73:13
|
LL | if let [(0 | 1)] = [0] {}
| ^ ^
@ -112,7 +136,7 @@ LL + if let [0 | 1] = [0] {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:59:16
--> $DIR/issue-54538-unused-parens-lint.rs:74:16
|
LL | if let 0 | (1 | 2) = 0 {}
| ^ ^
@ -124,7 +148,7 @@ LL + if let 0 | 1 | 2 = 0 {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:61:15
--> $DIR/issue-54538-unused-parens-lint.rs:76:15
|
LL | if let TS((0 | 1)) = TS(0) {}
| ^ ^
@ -136,7 +160,7 @@ LL + if let TS(0 | 1) = TS(0) {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:63:20
--> $DIR/issue-54538-unused-parens-lint.rs:78:20
|
LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
| ^ ^
@ -148,7 +172,7 @@ LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:73:9
--> $DIR/issue-54538-unused-parens-lint.rs:88:9
|
LL | (_) => {}
| ^ ^
@ -160,7 +184,7 @@ LL + _ => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:74:9
--> $DIR/issue-54538-unused-parens-lint.rs:89:9
|
LL | (y) => {}
| ^ ^
@ -172,7 +196,7 @@ LL + y => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:75:9
--> $DIR/issue-54538-unused-parens-lint.rs:90:9
|
LL | (ref r) => {}
| ^ ^
@ -184,7 +208,7 @@ LL + ref r => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:76:9
--> $DIR/issue-54538-unused-parens-lint.rs:91:9
|
LL | (e @ 1...2) => {}
| ^ ^
@ -196,7 +220,7 @@ LL + e @ 1...2 => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:82:9
--> $DIR/issue-54538-unused-parens-lint.rs:97:9
|
LL | (e @ &(1...2)) => {}
| ^ ^
@ -208,7 +232,7 @@ LL + e @ &(1...2) => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:83:10
--> $DIR/issue-54538-unused-parens-lint.rs:98:10
|
LL | &(_) => {}
| ^ ^
@ -220,7 +244,7 @@ LL + &_ => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:94:9
--> $DIR/issue-54538-unused-parens-lint.rs:109:9
|
LL | (_) => {}
| ^ ^
@ -232,7 +256,7 @@ LL + _ => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:95:9
--> $DIR/issue-54538-unused-parens-lint.rs:110:9
|
LL | (y) => {}
| ^ ^
@ -244,7 +268,7 @@ LL + y => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:96:9
--> $DIR/issue-54538-unused-parens-lint.rs:111:9
|
LL | (ref r) => {}
| ^ ^
@ -256,7 +280,7 @@ LL + ref r => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:97:9
--> $DIR/issue-54538-unused-parens-lint.rs:112:9
|
LL | (e @ 1..=2) => {}
| ^ ^
@ -268,7 +292,7 @@ LL + e @ 1..=2 => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:103:9
--> $DIR/issue-54538-unused-parens-lint.rs:118:9
|
LL | (e @ &(1..=2)) => {}
| ^ ^
@ -280,7 +304,7 @@ LL + e @ &(1..=2) => {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-54538-unused-parens-lint.rs:104:10
--> $DIR/issue-54538-unused-parens-lint.rs:119:10
|
LL | &(_) => {}
| ^ ^
@ -291,5 +315,5 @@ LL - &(_) => {}
LL + &_ => {}
|
error: aborting due to 24 previous errors
error: aborting due to 26 previous errors