Auto merge of #3711 - saethlin:rustup, r=saethlin

Manual Rustup

This bumps us to a rustc commit that doesn't have the chatty `./miri fmt` reported in https://rust-lang.zulipchat.com/#narrow/stream/269128-miri/topic/.22rewriting.20static.22.20printed.20during.20.2E.2Fmiri.20build
This commit is contained in:
bors 2024-06-25 22:33:35 +00:00
commit fc94ce216e
901 changed files with 8273 additions and 7046 deletions

View file

@ -427,11 +427,13 @@ pub struct Size {
raw: u64,
}
// Safety: Ord is implement as just comparing numerical values and numerical values
// are not changed by (de-)serialization.
#[cfg(feature = "nightly")]
unsafe impl StableOrd for Size {
impl StableOrd for Size {
const CAN_USE_UNSTABLE_SORT: bool = true;
// `Ord` is implemented as just comparing numerical values and numerical values
// are not changed by (de-)serialization.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
// This is debug-printed a lot in larger structs, don't waste too much space there

View file

@ -429,10 +429,10 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
) -> SmallVec<[PatField; 1]> {
let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_ident(ident);
vis.visit_pat(pat);
vis.visit_span(span);
visit_attrs(attrs, vis);
smallvec![fp]
}
@ -443,8 +443,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
UseTreeKind::Nested { items, .. } => {
for (tree, id) in items {
vis.visit_use_tree(tree);
vis.visit_id(id);
vis.visit_use_tree(tree);
}
}
UseTreeKind::Glob => {}
@ -454,8 +454,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
visit_attrs(attrs, vis);
vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_pat(pat);
visit_opt(guard, |guard| vis.visit_expr(guard));
visit_opt(body, |body| vis.visit_expr(body));
@ -548,10 +548,10 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
visitor: &mut T,
) -> SmallVec<[Variant; 1]> {
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
visitor.visit_id(id);
visit_attrs(attrs, visitor);
visitor.visit_ident(ident);
visitor.visit_vis(vis);
visit_attrs(attrs, visitor);
visitor.visit_id(id);
visitor.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
visitor.visit_span(span);
@ -565,8 +565,8 @@ fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mu
fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
vis.visit_span(span);
for PathSegment { ident, id, args } in segments {
vis.visit_ident(ident);
vis.visit_id(id);
vis.visit_ident(ident);
visit_opt(args, |args| vis.visit_generic_args(args));
}
visit_lazy_tts(tokens, vis);
@ -620,6 +620,7 @@ fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_pat(pat);
visit_opt(ty, |ty| vis.visit_ty(ty));
match kind {
@ -634,7 +635,6 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
}
vis.visit_span(span);
visit_opt(colon_sp, |sp| vis.visit_span(sp));
visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis);
}
@ -894,9 +894,9 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
| CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
| CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
vis.visit_span(span);
vis.visit_id(closure_id);
vis.visit_id(return_impl_trait_id);
vis.visit_span(span);
}
}
}
@ -932,8 +932,8 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
vis.visit_lifetime(lt);
}
PreciseCapturingArg::Arg(path, id) => {
vis.visit_path(path);
vis.visit_id(id);
vis.visit_path(path);
}
}
}
@ -944,11 +944,11 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
) -> SmallVec<[GenericParam; 1]> {
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_ident(ident);
if let Some(colon_span) = colon_span {
vis.visit_span(colon_span);
}
visit_attrs(attrs, vis);
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
match kind {
GenericParamKind::Lifetime => {}
@ -1015,16 +1015,16 @@ fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T)
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
}
VariantData::Tuple(fields, id) => {
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
vis.visit_id(id);
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
}
VariantData::Unit(id) => vis.visit_id(id),
}
}
fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
vis.visit_path(path);
vis.visit_id(ref_id);
vis.visit_path(path);
}
fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
@ -1039,12 +1039,12 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
visitor: &mut T,
) -> SmallVec<[FieldDef; 1]> {
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
visitor.visit_id(id);
visit_attrs(attrs, visitor);
visitor.visit_span(span);
visit_opt(ident, |ident| visitor.visit_ident(ident));
visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty);
visit_attrs(attrs, visitor);
smallvec![fd]
}
@ -1053,11 +1053,11 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
vis: &mut T,
) -> SmallVec<[ExprField; 1]> {
let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
vis.visit_id(id);
visit_attrs(attrs, vis);
vis.visit_ident(ident);
vis.visit_expr(expr);
vis.visit_id(id);
vis.visit_span(span);
visit_attrs(attrs, vis);
smallvec![f]
}
@ -1429,6 +1429,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
Expr { kind, id, span, attrs, tokens }: &mut Expr,
vis: &mut T,
) {
vis.visit_id(id);
visit_attrs(attrs, vis);
match kind {
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
ExprKind::ConstBlock(anon_const) => {
@ -1449,8 +1451,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
args: call_args,
span,
}) => {
vis.visit_ident(ident);
vis.visit_id(id);
vis.visit_ident(ident);
visit_opt(seg_args, |args| vis.visit_generic_args(args));
vis.visit_method_receiver_expr(receiver);
visit_thin_exprs(call_args, vis);
@ -1601,9 +1603,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
ExprKind::TryBlock(body) => vis.visit_block(body),
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
}
vis.visit_id(id);
vis.visit_span(span);
visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis);
}
@ -1645,8 +1645,8 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
StmtKind::Empty => smallvec![StmtKind::Empty],
StmtKind::MacCall(mut mac) => {
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
vis.visit_mac_call(mac_);
visit_attrs(attrs, vis);
vis.visit_mac_call(mac_);
visit_lazy_tts(tokens, vis);
smallvec![StmtKind::MacCall(mac)]
}
@ -1657,8 +1657,8 @@ fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
match &mut visibility.kind {
VisibilityKind::Public | VisibilityKind::Inherited => {}
VisibilityKind::Restricted { path, id, shorthand: _ } => {
vis.visit_path(path);
vis.visit_id(id);
vis.visit_path(path);
}
}
vis.visit_span(&mut visibility.span);

View file

@ -298,8 +298,8 @@ pub trait Visitor<'ast>: Sized {
}
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
walk_list!(visitor, visit_item, &krate.items);
walk_list!(visitor, visit_attribute, &krate.attrs);
walk_list!(visitor, visit_item, &krate.items);
V::Result::output()
}
@ -462,25 +462,25 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -
where
V: Visitor<'a>,
{
walk_list!(visitor, visit_attribute, &variant.attrs);
try_visit!(visitor.visit_ident(variant.ident));
try_visit!(visitor.visit_vis(&variant.vis));
try_visit!(visitor.visit_variant_data(&variant.data));
visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
walk_list!(visitor, visit_attribute, &variant.attrs);
V::Result::output()
}
pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
walk_list!(visitor, visit_attribute, &f.attrs);
try_visit!(visitor.visit_expr(&f.expr));
try_visit!(visitor.visit_ident(f.ident));
walk_list!(visitor, visit_attribute, &f.attrs);
V::Result::output()
}
pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
walk_list!(visitor, visit_attribute, &fp.attrs);
try_visit!(visitor.visit_ident(fp.ident));
try_visit!(visitor.visit_pat(&fp.pat));
walk_list!(visitor, visit_attribute, &fp.attrs);
V::Result::output()
}
@ -722,8 +722,8 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
visitor: &mut V,
param: &'a GenericParam,
) -> V::Result {
try_visit!(visitor.visit_ident(param.ident));
walk_list!(visitor, visit_attribute, &param.attrs);
try_visit!(visitor.visit_ident(param.ident));
walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
match &param.kind {
GenericParamKind::Lifetime => (),
@ -882,10 +882,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
ctxt: AssocCtxt,
) -> V::Result {
let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_vis(vis));
try_visit!(visitor.visit_ident(ident));
try_visit!(kind.walk(item, ctxt, visitor));
walk_list!(visitor, visit_attribute, attrs);
V::Result::output()
}
@ -898,10 +898,10 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(
}
pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
walk_list!(visitor, visit_attribute, &field.attrs);
try_visit!(visitor.visit_vis(&field.vis));
visit_opt!(visitor, visit_ident, field.ident);
try_visit!(visitor.visit_ty(&field.ty));
walk_list!(visitor, visit_attribute, &field.attrs);
V::Result::output()
}
@ -918,8 +918,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V:
StmtKind::Empty => {}
StmtKind::MacCall(mac) => {
let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
try_visit!(visitor.visit_mac_call(mac));
walk_list!(visitor, visit_attribute, attrs);
try_visit!(visitor.visit_mac_call(mac));
}
}
V::Result::output()
@ -1141,10 +1141,10 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::R
}
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
walk_list!(visitor, visit_attribute, &arm.attrs);
try_visit!(visitor.visit_pat(&arm.pat));
visit_opt!(visitor, visit_expr, &arm.guard);
visit_opt!(visitor, visit_expr, &arm.body);
walk_list!(visitor, visit_attribute, &arm.attrs);
V::Result::output()
}

View file

@ -6,7 +6,7 @@ use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
self.infcx.dcx()
}

View file

@ -52,7 +52,7 @@ impl<'tcx> UniverseInfo<'tcx> {
pub(crate) fn report_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
cause: ObligationCause<'tcx>,
@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> {
fn nice_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@ -160,7 +160,7 @@ trait TypeOpInfo<'tcx> {
#[instrument(level = "debug", skip(self, mbcx))]
fn report_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
cause: ObligationCause<'tcx>,
@ -233,7 +233,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
fn nice_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@ -270,7 +270,7 @@ where
fn nice_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@ -310,7 +310,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
fn nice_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@ -336,7 +336,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
fn nice_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
_cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,

View file

@ -73,7 +73,7 @@ enum StorageDeadOrDrop<'tcx> {
Destructor(Ty<'tcx>),
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub(crate) fn report_use_of_moved_or_uninitialized(
&mut self,
location: Location,
@ -4243,7 +4243,11 @@ enum AnnotatedBorrowFnSignature<'tcx> {
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diag<'_>) -> String {
pub(crate) fn emit(
&self,
cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>,
diag: &mut Diag<'_>,
) -> String {
match self {
&AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
diag.span_label(

View file

@ -389,7 +389,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
fn free_region_constraint_info(
&self,
borrow_region: RegionVid,

View file

@ -69,7 +69,7 @@ pub(super) struct DescribePlaceOpt {
pub(super) struct IncludingTupleField(pub(super) bool);
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
/// is moved after being invoked.
///
@ -771,7 +771,7 @@ struct CapturedMessageOpt {
maybe_reinitialized_locations_is_empty: bool,
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
&self,

View file

@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
},
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub(crate) fn report_move_errors(&mut self) {
let grouped_errors = self.group_move_errors();
for error in grouped_errors {

View file

@ -30,7 +30,7 @@ pub(crate) enum AccessKind {
Mutate,
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub(crate) fn report_mutability_error(
&mut self,
access_place: Place<'tcx>,

View file

@ -75,7 +75,7 @@ impl OutlivesSuggestionBuilder {
/// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
fn region_vid_to_name(
&self,
mbcx: &MirBorrowckCtxt<'_, '_>,
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
region: RegionVid,
) -> Option<RegionName> {
mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
@ -84,7 +84,7 @@ impl OutlivesSuggestionBuilder {
/// Compiles a list of all suggestions to be printed in the final big suggestion.
fn compile_all_suggestions(
&self,
mbcx: &MirBorrowckCtxt<'_, '_>,
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
) -> SmallVec<[SuggestedConstraint; 2]> {
let mut suggested = SmallVec::new();
@ -160,7 +160,7 @@ impl OutlivesSuggestionBuilder {
/// Emit an intermediate note on the given `Diag` if the involved regions are suggestable.
pub(crate) fn intermediate_suggestion(
&mut self,
mbcx: &MirBorrowckCtxt<'_, '_>,
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
errci: &ErrorConstraintInfo<'_>,
diag: &mut Diag<'_>,
) {
@ -179,7 +179,7 @@ impl OutlivesSuggestionBuilder {
/// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
/// suggestion including all collected constraints.
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) {
// No constraints to add? Done.
if self.constraints_to_add.is_empty() {
debug!("No constraints to suggest.");

View file

@ -160,7 +160,7 @@ pub struct ErrorConstraintInfo<'tcx> {
pub(super) span: Span,
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
/// Converts a region inference variable into a `ty::Region` that
/// we can use for error reporting. If `r` is universally bound,
/// then we use the name that we have on record for it. If `r` is

View file

@ -198,7 +198,7 @@ impl rustc_errors::IntoDiagArg for RegionName {
}
}
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
self.body.source.def_id().expect_local()
}

View file

@ -310,11 +310,11 @@ fn do_mir_borrowck<'tcx>(
promoted_mbcx.report_move_errors();
diags = promoted_mbcx.diags;
struct MoveVisitor<'a, 'cx, 'tcx> {
ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>,
struct MoveVisitor<'a, 'b, 'mir, 'cx, 'tcx> {
ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'cx, 'tcx>,
}
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
if let Operand::Move(place) = operand {
self.ctxt.check_movable_place(location, *place);
@ -528,15 +528,15 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
}
}
struct MirBorrowckCtxt<'cx, 'tcx> {
struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
body: &'mir Body<'tcx>,
move_data: &'a MoveData<'tcx>,
/// Map from MIR `Location` to `LocationIndex`; created
/// when MIR borrowck begins.
location_table: &'cx LocationTable,
location_table: &'a LocationTable,
movable_coroutine: bool,
/// This keeps track of whether local variables are free-ed when the function
@ -605,14 +605,16 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
type FlowState = Flows<'cx, 'tcx>;
impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
for MirBorrowckCtxt<'_, 'mir, '_, 'tcx>
{
type FlowState = Flows<'mir, 'tcx>;
fn visit_statement_before_primary_effect(
&mut self,
_results: &mut R,
flow_state: &Flows<'cx, 'tcx>,
stmt: &'cx Statement<'tcx>,
flow_state: &Flows<'mir, 'tcx>,
stmt: &'mir Statement<'tcx>,
location: Location,
) {
debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state);
@ -681,8 +683,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
fn visit_terminator_before_primary_effect(
&mut self,
_results: &mut R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
flow_state: &Flows<'mir, 'tcx>,
term: &'mir Terminator<'tcx>,
loc: Location,
) {
debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state);
@ -792,8 +794,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
fn visit_terminator_after_primary_effect(
&mut self,
_results: &mut R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
flow_state: &Flows<'mir, 'tcx>,
term: &'mir Terminator<'tcx>,
loc: Location,
) {
let span = term.source_info.span;
@ -969,8 +971,8 @@ impl InitializationRequiringAction {
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn body(&self) -> &'cx Body<'tcx> {
impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
fn body(&self) -> &'mir Body<'tcx> {
self.body
}
@ -986,7 +988,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_span: (Place<'tcx>, Span),
kind: (AccessDepth, ReadOrWrite),
is_local_mutation_allowed: LocalMutationIsAllowed,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
let (sd, rw) = kind;
@ -1036,7 +1038,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_span: (Place<'tcx>, Span),
sd: AccessDepth,
rw: ReadOrWrite,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) -> bool {
let mut error_reported = false;
let borrow_set = Rc::clone(&self.borrow_set);
@ -1177,7 +1179,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
place_span: (Place<'tcx>, Span),
kind: AccessDepth,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
// Write of P[i] or *P requires P init'd.
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
@ -1194,8 +1196,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn consume_rvalue(
&mut self,
location: Location,
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
(rvalue, span): (&'mir Rvalue<'tcx>, Span),
flow_state: &Flows<'mir, 'tcx>,
) {
match rvalue {
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
@ -1452,8 +1454,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn consume_operand(
&mut self,
location: Location,
(operand, span): (&'cx Operand<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
(operand, span): (&'mir Operand<'tcx>, Span),
flow_state: &Flows<'mir, 'tcx>,
) {
match *operand {
Operand::Copy(place) => {
@ -1573,7 +1575,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'cx, 'tcx>) {
fn check_activations(
&mut self,
location: Location,
span: Span,
flow_state: &Flows<'mir, 'tcx>,
) {
// Two-phase borrow support: For each activation that is newly
// generated at this statement, check if it interferes with
// another borrow.
@ -1736,7 +1743,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
desired_action: InitializationRequiringAction,
place_span: (PlaceRef<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@ -1841,7 +1848,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
desired_action: InitializationRequiringAction,
place_span: (PlaceRef<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@ -1940,7 +1947,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&mut self,
location: Location,
(place, span): (Place<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
debug!("check_if_assigned_path_is_moved place: {:?}", place);
@ -2001,12 +2008,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
fn check_parent_of_field<'cx, 'tcx>(
this: &mut MirBorrowckCtxt<'cx, 'tcx>,
fn check_parent_of_field<'mir, 'tcx>(
this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>,
location: Location,
base: PlaceRef<'tcx>,
span: Span,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) {
// rust-lang/rust#21232: Until Rust allows reads from the
// initialized parts of partially initialized structs, we
@ -2097,7 +2104,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(place, span): (Place<'tcx>, Span),
kind: ReadOrWrite,
is_local_mutation_allowed: LocalMutationIsAllowed,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
location: Location,
) -> bool {
debug!(
@ -2213,7 +2220,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn is_local_ever_initialized(
&self,
local: Local,
flow_state: &Flows<'cx, 'tcx>,
flow_state: &Flows<'mir, 'tcx>,
) -> Option<InitIndex> {
let mpi = self.move_data.rev_lookup.find_local(local)?;
let ii = &self.move_data.init_path_map[mpi];
@ -2221,7 +2228,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
/// Adds the place into the used mutable variables set
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'mir, 'tcx>) {
match root_place {
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
// If the local may have been initialized, and it is now currently being
@ -2476,7 +2483,7 @@ mod diags {
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
self.diags.buffer_error(diag);
}

View file

@ -34,7 +34,7 @@ pub(super) enum PrefixSet {
Shallow,
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
/// Returns an iterator over the prefixes of `place`
/// (inclusive) from longest to smallest, potentially
/// terminating the iteration early based on `kind`.

View file

@ -6,7 +6,7 @@ use rustc_middle::mir::{
use crate::MirBorrowckCtxt;
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
/// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
/// of the `unused_mut` lint.
///
@ -45,13 +45,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// MIR visitor for collecting used mutable variables.
/// The 'visit lifetime represents the duration of the MIR walk.
struct GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'cx, 'tcx> {
temporary_used_locals: FxIndexSet<Local>,
never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'tcx>,
mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx>,
}
impl GatherUsedMutsVisitor<'_, '_, '_> {
impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
// Remove any locals that we found were initialized from the
// `never_initialized_mut_locals` set. At the end, the only remaining locals will
@ -63,7 +63,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_> {
}
}
impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
debug!("visit_terminator: terminator={:?}", terminator);
match &terminator.kind {

View file

@ -27,6 +27,7 @@ pub(crate) mod decodable;
pub(crate) mod default;
pub(crate) mod encodable;
pub(crate) mod hash;
pub(crate) mod smart_ptr;
#[path = "cmp/eq.rs"]
pub(crate) mod eq;

View file

@ -0,0 +1,140 @@
use std::mem::swap;
use ast::HasAttrs;
use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
TraitBoundModifiers,
};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
use thin_vec::{thin_vec, ThinVec};
macro_rules! path {
($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] }
}
pub fn expand_deriving_smart_ptr(
cx: &ExtCtxt<'_>,
span: Span,
_mitem: &MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable),
_is_const: bool,
) {
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
&& let ItemKind::Struct(_, g) = &aitem.kind
{
(aitem.ident, g)
} else {
cx.dcx().struct_span_err(span, "`SmartPointer` can only be derived on `struct`s").emit();
return;
};
// Convert generic parameters (from the struct) into generic args.
let mut pointee_param = None;
let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![];
let self_params = generics
.params
.iter()
.enumerate()
.map(|(idx, p)| match p.kind {
GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)),
GenericParamKind::Type { .. } => {
if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) {
if pointee_param.is_some() {
multiple_pointee_diag.push(cx.dcx().struct_span_err(
p.span(),
"`SmartPointer` can only admit one type as pointee",
));
} else {
pointee_param = Some(idx);
}
}
GenericArg::Type(cx.ty_ident(p.span(), p.ident))
}
GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)),
})
.collect::<Vec<_>>();
let Some(pointee_param_idx) = pointee_param else {
cx.dcx().struct_span_err(
span,
"At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits",
).emit();
return;
};
if !multiple_pointee_diag.is_empty() {
for diag in multiple_pointee_diag {
diag.emit();
}
return;
}
// Create the type of `self`.
let path = cx.path_all(span, false, vec![name_ident], self_params.clone());
let self_type = cx.ty_path(path);
// Declare helper function that adds implementation blocks.
// FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
let mut add_impl_block = |generics, trait_symbol, trait_args| {
let mut parts = path!(span, core::ops);
parts.push(Ident::new(trait_symbol, span));
let trait_path = cx.path_all(span, true, parts, trait_args);
let trait_ref = cx.trait_ref(trait_path);
let item = cx.item(
span,
Ident::empty(),
attrs.clone(),
ast::ItemKind::Impl(Box::new(ast::Impl {
safety: ast::Safety::Default,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: ast::Const::No,
generics,
of_trait: Some(trait_ref),
self_ty: self_type.clone(),
items: ThinVec::new(),
})),
);
push(Annotatable::Item(item));
};
// Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For
// example, instead of `MyType<'a, T>`, it will be `MyType<'a, __S>`.
let s_ty = cx.ty_ident(span, Ident::new(sym::__S, span));
let mut alt_self_params = self_params;
alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone());
let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params));
// Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
let mut impl_generics = generics.clone();
{
let p = &mut impl_generics.params[pointee_param_idx];
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
p.bounds.push(cx.trait_bound(unsize, false));
let mut attrs = thin_vec![];
swap(&mut p.attrs, &mut attrs);
p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
}
// Add the `__S: ?Sized` extra parameter to the impl block.
let sized = cx.path_global(span, path!(span, core::marker::Sized));
let bound = GenericBound::Trait(
cx.poly_trait_ref(span, sized),
TraitBoundModifiers {
polarity: ast::BoundPolarity::Maybe(span),
constness: ast::BoundConstness::Never,
asyncness: ast::BoundAsyncness::Normal,
},
);
let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None);
impl_generics.params.push(extra_param);
// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone());
}

View file

@ -127,6 +127,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
PartialOrd: partial_ord::expand_deriving_partial_ord,
RustcDecodable: decodable::expand_deriving_rustc_decodable,
RustcEncodable: encodable::expand_deriving_rustc_encodable,
SmartPointer: smart_ptr::expand_deriving_smart_ptr,
}
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);

View file

@ -564,9 +564,6 @@ pub(crate) unsafe fn llvm_optimize(
let llvm_plugins = config.llvm_plugins.join(",");
// FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
// We would have to add upstream support for this first, before we can support
// config.inline_threshold and our more aggressive default thresholds.
let result = llvm::LLVMRustOptimize(
module.module_llvm.llmod(),
&*module.module_llvm.tm,

View file

@ -27,8 +27,6 @@ codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
codegen_ssa_expected_coverage_symbol = expected `coverage(off)` or `coverage(on)`
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified

View file

@ -120,7 +120,6 @@ pub struct ModuleConfig {
pub vectorize_loop: bool,
pub vectorize_slp: bool,
pub merge_functions: bool,
pub inline_threshold: Option<u32>,
pub emit_lifetime_markers: bool,
pub llvm_plugins: Vec<String>,
}
@ -280,7 +279,6 @@ impl ModuleConfig {
}
},
inline_threshold: sess.opts.cg.inline_threshold,
emit_lifetime_markers: sess.emit_lifetime_markers(),
llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
}

View file

@ -15,11 +15,7 @@ use rustc_span::{sym, Span};
use rustc_target::spec::{abi, SanitizerSet};
use crate::errors;
use crate::target_features::from_target_feature;
use crate::{
errors::{ExpectedCoverageSymbol, ExpectedUsedSymbol},
target_features::check_target_feature_trait_unsafe,
};
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
use rustc_middle::mir::mono::Linkage::*;
@ -139,7 +135,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
// coverage on a smaller scope within an excluded larger scope.
}
Some(_) | None => {
tcx.dcx().emit_err(ExpectedCoverageSymbol { span: attr.span });
tcx.dcx()
.span_delayed_bug(attr.span, "unexpected value of coverage attribute");
}
}
}
@ -174,7 +171,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
}
Some(_) => {
tcx.dcx().emit_err(ExpectedUsedSymbol { span: attr.span });
tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span });
}
None => {
// Unfortunately, unconditionally using `llvm.used` causes

View file

@ -564,13 +564,6 @@ pub struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_coverage_symbol)]
pub struct ExpectedCoverageSymbol {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_used_symbol)]
pub struct ExpectedUsedSymbol {

View file

@ -27,7 +27,6 @@
#![feature(lint_reasons)]
#![feature(macro_metavar_expr)]
#![feature(map_try_insert)]
#![feature(maybe_uninit_uninit_array)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]

View file

@ -188,7 +188,7 @@ impl SipHasher128 {
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 {
let mut hasher = SipHasher128 {
nbuf: 0,
buf: MaybeUninit::uninit_array(),
buf: [MaybeUninit::uninit(); BUFFER_WITH_SPILL_CAPACITY],
state: State {
v0: key0 ^ 0x736f6d6570736575,
// The XOR with 0xee is only done on 128-bit algorithm version.

View file

@ -238,12 +238,21 @@ pub trait ToStableHashKey<HCX> {
/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
/// unstable sorting can be used for this type. Set to true if and
/// only if `a == b` implies `a` and `b` are fully indistinguishable.
pub unsafe trait StableOrd: Ord {
pub trait StableOrd: Ord {
const CAN_USE_UNSTABLE_SORT: bool;
/// Marker to ensure that implementors have carefully considered
/// whether their `Ord` implementation obeys this trait's contract.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: ();
}
unsafe impl<T: StableOrd> StableOrd for &T {
impl<T: StableOrd> StableOrd for &T {
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
// Ordering of a reference is exactly that of the referent, and since
// the ordering of the referet is stable so must be the ordering of the
// reference.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
@ -290,8 +299,12 @@ macro_rules! impl_stable_traits_for_trivial_type {
}
}
unsafe impl $crate::stable_hasher::StableOrd for $t {
impl $crate::stable_hasher::StableOrd for $t {
const CAN_USE_UNSTABLE_SORT: bool = true;
// Encoding and decoding doesn't change the bytes of trivial types
// and `Ord::cmp` depends only on those bytes.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
};
}
@ -327,8 +340,12 @@ impl<CTX> HashStable<CTX> for Hash128 {
}
}
unsafe impl StableOrd for Hash128 {
impl StableOrd for Hash128 {
const CAN_USE_UNSTABLE_SORT: bool = true;
// Encoding and decoding doesn't change the bytes of `Hash128`
// and `Ord::cmp` depends only on those bytes.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<CTX> HashStable<CTX> for ! {
@ -392,8 +409,12 @@ impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2)
}
}
unsafe impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT;
// Ordering of tuples is a pure function of their elements' ordering, and since
// the ordering of each element is stable so must be the ordering of the tuple.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
@ -410,9 +431,13 @@ where
}
}
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
const CAN_USE_UNSTABLE_SORT: bool =
T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
// Ordering of tuples is a pure function of their elements' ordering, and since
// the ordering of each element is stable so must be the ordering of the tuple.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
@ -431,13 +456,15 @@ where
}
}
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd
for (T1, T2, T3, T4)
{
impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
&& T2::CAN_USE_UNSTABLE_SORT
&& T3::CAN_USE_UNSTABLE_SORT
&& T4::CAN_USE_UNSTABLE_SORT;
// Ordering of tuples is a pure function of their elements' ordering, and since
// the ordering of each element is stable so must be the ordering of the tuple.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
@ -530,8 +557,12 @@ impl<CTX> HashStable<CTX> for str {
}
}
unsafe impl StableOrd for &str {
impl StableOrd for &str {
const CAN_USE_UNSTABLE_SORT: bool = true;
// Encoding and decoding doesn't change the bytes of string slices
// and `Ord::cmp` depends only on those bytes.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<CTX> HashStable<CTX> for String {
@ -541,10 +572,12 @@ impl<CTX> HashStable<CTX> for String {
}
}
// Safety: String comparison only depends on their contents and the
// contents are not changed by (de-)serialization.
unsafe impl StableOrd for String {
impl StableOrd for String {
const CAN_USE_UNSTABLE_SORT: bool = true;
// String comparison only depends on their contents and the
// contents are not changed by (de-)serialization.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<HCX> ToStableHashKey<HCX> for String {
@ -570,9 +603,11 @@ impl<CTX> HashStable<CTX> for bool {
}
}
// Safety: sort order of bools is not changed by (de-)serialization.
unsafe impl StableOrd for bool {
impl StableOrd for bool {
const CAN_USE_UNSTABLE_SORT: bool = true;
// sort order of bools is not changed by (de-)serialization.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<T, CTX> HashStable<CTX> for Option<T>
@ -590,9 +625,11 @@ where
}
}
// Safety: the Option wrapper does not add instability to comparison.
unsafe impl<T: StableOrd> StableOrd for Option<T> {
impl<T: StableOrd> StableOrd for Option<T> {
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
// the Option wrapper does not add instability to comparison.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>

View file

@ -30,7 +30,7 @@ use rustc_errors::{
};
use rustc_feature::find_gated_cfg;
use rustc_interface::util::{self, get_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_interface::{interface, passes, Queries};
use rustc_lint::unerased_lint_store;
use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::locator;
@ -367,18 +367,17 @@ fn run_compiler(
return early_exit();
}
let early_dcx = EarlyDiagCtxt::new(sess.opts.error_format);
if print_crate_info(&early_dcx, codegen_backend, sess, has_input) == Compilation::Stop {
if print_crate_info(codegen_backend, sess, has_input) == Compilation::Stop {
return early_exit();
}
if !has_input {
early_dcx.early_fatal("no input filename given"); // this is fatal
#[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("no input filename given"); // this is fatal
}
if !sess.opts.unstable_opts.ls.is_empty() {
list_metadata(&early_dcx, sess, &*codegen_backend.metadata_loader());
list_metadata(sess, &*codegen_backend.metadata_loader());
return early_exit();
}
@ -399,7 +398,9 @@ fn run_compiler(
Ok(())
})?;
queries.write_dep_info()?;
queries.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
} else {
let krate = queries.parse()?;
pretty::print(
@ -427,7 +428,9 @@ fn run_compiler(
return early_exit();
}
queries.write_dep_info()?;
queries.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
@ -670,7 +673,7 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
}
}
fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dyn MetadataLoader) {
fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
match sess.io.input {
Input::File(ref ifile) => {
let path = &(*ifile);
@ -687,13 +690,13 @@ fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dy
safe_println!("{}", String::from_utf8(v).unwrap());
}
Input::Str { .. } => {
early_dcx.early_fatal("cannot list metadata for stdin");
#[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("cannot list metadata for stdin");
}
}
}
fn print_crate_info(
early_dcx: &EarlyDiagCtxt,
codegen_backend: &dyn CodegenBackend,
sess: &Session,
parse_attrs: bool,
@ -877,8 +880,8 @@ fn print_crate_info(
.expect("unknown Apple target OS");
println_info!("deployment_target={}", format!("{major}.{minor}"))
} else {
early_dcx
.early_fatal("only Apple targets currently support deployment version info")
#[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("only Apple targets currently support deployment version info")
}
}
}
@ -1133,7 +1136,11 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
}
if cg_flags.iter().any(|x| *x == "no-stack-check") {
early_dcx.early_warn("the --no-stack-check flag is deprecated and does nothing");
early_dcx.early_warn("the `-Cno-stack-check` flag is deprecated and does nothing");
}
if cg_flags.iter().any(|x| x.starts_with("inline-threshold")) {
early_dcx.early_warn("the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)");
}
if cg_flags.iter().any(|x| *x == "passes=list") {

View file

@ -902,7 +902,7 @@ impl HumanEmitter {
// <EMPTY LINE>
//
let mut annotations_position = vec![];
let mut line_len = 0;
let mut line_len: usize = 0;
let mut p = 0;
for (i, annotation) in annotations.iter().enumerate() {
for (j, next) in annotations.iter().enumerate() {
@ -973,6 +973,31 @@ impl HumanEmitter {
return vec![];
}
if annotations_position
.iter()
.all(|(_, ann)| matches!(ann.annotation_type, AnnotationType::MultilineStart(_)))
&& let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max()
{
// Special case the following, so that we minimize overlapping multiline spans.
//
// 3 │ X0 Y0 Z0
// │ ┏━━━━━┛ │ │ < We are writing these lines
// │ ┃┌───────┘ │ < by reverting the "depth" of
// │ ┃│┌─────────┘ < their multilne spans.
// 4 │ ┃││ X1 Y1 Z1
// 5 │ ┃││ X2 Y2 Z2
// │ ┃│└────╿──│──┘ `Z` label
// │ ┃└─────│──┤
// │ ┗━━━━━━┥ `Y` is a good letter too
// ╰╴ `X` is a good letter
for (pos, _) in &mut annotations_position {
*pos = max_pos - *pos;
}
// We know then that we don't need an additional line for the span label, saving us
// one line of vertical space.
line_len = line_len.saturating_sub(1);
}
// Write the column separator.
//
// After this we will have:

View file

@ -105,6 +105,9 @@ pub struct AttributeTemplate {
pub word: bool,
/// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`.
pub list: Option<&'static str>,
/// If non-empty, the attribute is allowed to take a list containing exactly
/// one of the listed words, like `#[coverage(off)]`.
pub one_of: &'static [Symbol],
/// If `Some`, the attribute is allowed to be a name/value pair where the
/// value is a string, like `#[must_use = "reason"]`.
pub name_value_str: Option<&'static str>,
@ -165,19 +168,20 @@ pub enum AttributeDuplicates {
/// E.g., `template!(Word, List: "description")` means that the attribute
/// supports forms `#[attr]` and `#[attr(description)]`.
macro_rules! template {
(Word) => { template!(@ true, None, None) };
(List: $descr: expr) => { template!(@ false, Some($descr), None) };
(NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) };
(Word, List: $descr: expr) => { template!(@ true, Some($descr), None) };
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) };
(Word) => { template!(@ true, None, &[], None) };
(List: $descr: expr) => { template!(@ false, Some($descr), &[], None) };
(OneOf: $one_of: expr) => { template!(@ false, None, $one_of, None) };
(NameValueStr: $descr: expr) => { template!(@ false, None, &[], Some($descr)) };
(Word, List: $descr: expr) => { template!(@ true, Some($descr), &[], None) };
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, &[], Some($descr)) };
(List: $descr1: expr, NameValueStr: $descr2: expr) => {
template!(@ false, Some($descr1), Some($descr2))
template!(@ false, Some($descr1), &[], Some($descr2))
};
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
template!(@ true, Some($descr1), Some($descr2))
template!(@ true, Some($descr1), &[], Some($descr2))
};
(@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
word: $word, list: $list, name_value_str: $name_value_str
(@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { AttributeTemplate {
word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str
} };
}
@ -478,8 +482,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::No, experimental!(no_sanitize)
),
gated!(
coverage, Normal, template!(Word, List: "on|off"),
WarnFollowing, EncodeCrossCrate::No,
coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
ErrorPreceding, EncodeCrossCrate::No,
coverage_attribute, experimental!(coverage)
),
@ -575,6 +579,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::No, coroutines, experimental!(coroutines)
),
// `#[pointee]` attribute to designate the pointee type in SmartPointer derive-macro
gated!(
pointee, Normal, template!(Word), ErrorFollowing,
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
),
// ==========================================================================
// Internal attributes: Stability, deprecation, and unsafe:
// ==========================================================================

View file

@ -436,6 +436,8 @@ declare_features! (
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
/// Allows deref patterns.
(incomplete, deref_patterns, "1.79.0", Some(87121)),
/// Allows deriving `SmartPointer` traits
(unstable, derive_smart_pointer, "1.79.0", Some(123430)),
/// Controls errors in trait implementations.
(unstable, do_not_recommend, "1.67.0", Some(51992)),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.

View file

@ -165,10 +165,12 @@ impl ItemLocalId {
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
}
// Safety: Ord is implement as just comparing the ItemLocalId's numerical
// values and these are not changed by (de-)serialization.
unsafe impl StableOrd for ItemLocalId {
impl StableOrd for ItemLocalId {
const CAN_USE_UNSTABLE_SORT: bool = true;
// `Ord` is implemented as just comparing the ItemLocalId's numerical
// values and these are not changed by (de-)serialization.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.

View file

@ -719,7 +719,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
tcx,
assoc_item,
assoc_item,
ty::TraitRef::new(tcx, def_id.to_def_id(), trait_args),
ty::TraitRef::new_from_args(tcx, def_id.to_def_id(), trait_args),
);
}
_ => {}

View file

@ -2032,7 +2032,7 @@ pub(super) fn check_type_bounds<'tcx>(
// to its definition type. This should be the param-env we use to *prove* the
// predicate too, but we don't do that because of performance issues.
// See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
let trait_projection_ty = Ty::new_projection(tcx, trait_ty.def_id, rebased_args);
let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
for mut obligation in util::elaborate(tcx, obligations) {
@ -2230,7 +2230,11 @@ fn param_env_with_gat_bounds<'tcx>(
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_term: ty::AliasTerm::new(tcx, trait_ty.def_id, rebased_args),
projection_term: ty::AliasTerm::new_from_args(
tcx,
trait_ty.def_id,
rebased_args,
),
term: normalize_impl_ty.into(),
},
bound_vars,

View file

@ -504,7 +504,11 @@ pub fn check_intrinsic_type(
ty::Region::new_bound(tcx, ty::INNERMOST, br),
param(0),
)],
Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])),
Ty::new_projection_from_args(
tcx,
discriminant_def_id,
tcx.mk_args(&[param(0).into()]),
),
)
}

View file

@ -423,7 +423,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
item_segment,
trait_ref.args,
);
Ty::new_projection(self.tcx(), item_def_id, item_args)
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
} else {
// There are no late-bound regions; we can just ignore the binder.
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@ -1607,7 +1607,7 @@ pub fn suggest_impl_trait<'tcx>(
let item_ty = ocx.normalize(
&ObligationCause::dummy(),
param_env,
Ty::new_projection(infcx.tcx, assoc_item_def_id, args),
Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
);
// FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty()

View file

@ -23,7 +23,7 @@ fn associated_type_bounds<'tcx>(
span: Span,
filter: PredicateFilter,
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
let item_ty = Ty::new_projection(
let item_ty = Ty::new_projection_from_args(
tcx,
assoc_item_def_id.to_def_id(),
GenericArgs::identity_for_item(tcx, assoc_item_def_id),
@ -108,7 +108,7 @@ pub(super) fn explicit_item_bounds_with_filter(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
Ty::new_projection(
Ty::new_projection_from_args(
tcx,
def_id.to_def_id(),
ty::GenericArgs::identity_for_item(tcx, def_id),

View file

@ -409,7 +409,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
debug!(?alias_args);
ty::AliasTerm::new(tcx, assoc_item.def_id, alias_args)
ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
});
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.

View file

@ -693,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?bound_vars);
let poly_trait_ref = ty::Binder::bind_with_vars(
ty::TraitRef::new(tcx, trait_def_id, generic_args),
ty::TraitRef::new_from_args(tcx, trait_def_id, generic_args),
bound_vars,
);
@ -759,7 +759,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some((trait_def_id, trait_segment, span)),
);
}
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
ty::TraitRef::new_from_args(self.tcx(), trait_def_id, generic_args)
}
fn probe_trait_that_defines_assoc_item(
@ -789,7 +789,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Type aliases defined in crates that have the
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
// then actually instantiate the where bounds of.
let alias_ty = ty::AliasTy::new(tcx, did, args);
let alias_ty = ty::AliasTy::new_from_args(tcx, did, args);
Ty::new_alias(tcx, ty::Weak, alias_ty)
} else {
tcx.at(span).type_of(did).instantiate(tcx, args)
@ -1267,7 +1267,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.chain(args.into_iter().skip(parent_args.len())),
);
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
let ty =
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
Ok(Some((ty, assoc_item)))
}
@ -1534,7 +1535,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let item_args =
self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
Ty::new_projection(tcx, item_def_id, item_args)
Ty::new_projection_from_args(tcx, item_def_id, item_args)
}
pub fn prohibit_generic_args<'a>(
@ -2302,7 +2303,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?args);
if in_trait {
Ty::new_projection(tcx, def_id, args)
Ty::new_projection_from_args(tcx, def_id, args)
} else {
Ty::new_opaque(tcx, def_id, args)
}

View file

@ -1245,11 +1245,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr,
);
return self
return Err(self
.commit_if_ok(|_| {
self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty)
self.at(cause, self.param_env).lub(DefineOpaqueTypes::Yes, prev_ty, new_ty)
})
.map(|ok| self.register_infer_ok_obligations(ok));
.unwrap_err());
}
}
@ -1259,10 +1259,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(e) = first_error {
Err(e)
} else {
self.commit_if_ok(|_| {
self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty)
})
.map(|ok| self.register_infer_ok_obligations(ok))
Err(self
.commit_if_ok(|_| {
self.at(cause, self.param_env).lub(
DefineOpaqueTypes::Yes,
prev_ty,
new_ty,
)
})
.unwrap_err())
}
}
Ok(ok) => {

View file

@ -3108,7 +3108,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let element_ty = ocx.normalize(
&cause,
self.param_env,
Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
Ty::new_projection_from_args(
self.tcx,
index_trait_output_def_id,
impl_trait_ref.args,
),
);
let true_errors = ocx.select_where_possible();

View file

@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
// that struct type.
let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
ty::TraitRef::new(
ty::TraitRef::new_from_args(
self.tcx,
obligation.impl_or_alias_def_id,
ty::GenericArgs::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),

View file

@ -297,7 +297,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
trait_ref.args,
);
Ty::new_projection(self.tcx(), item_def_id, item_args)
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
}
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {

View file

@ -73,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Special-case transmuting from `typeof(function)` and
// `Option<typeof(function)>` to present a clearer error.
let from = unpack_option_like(tcx, from);
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to)
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
{
struct_span_code_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type")
@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Try to display a sensible error with as much information as possible.
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
Ok(SizeSkeleton::Known(size)) => {
Ok(SizeSkeleton::Known(size, _)) => {
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
format!("{v} bits")
} else {

View file

@ -333,7 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.var_for_def(cause.span, param)
});
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, args);
let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, args);
// Construct an obligation
let poly_trait_ref = ty::Binder::dummy(trait_ref);

View file

@ -870,7 +870,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
trait_def_id: DefId,
) {
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args);
if self.tcx.is_trait_alias(trait_def_id) {
// For trait aliases, recursively assume all explicitly named traits are relevant

View file

@ -1978,7 +1978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err,
self_source,
args,
ty::TraitRef::new(
ty::TraitRef::new_from_args(
self.tcx,
trait_did,
self.fresh_args_for_item(sugg_span, trait_did),

View file

@ -256,12 +256,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
(false, None, None, Some(span), String::new())
};
let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
self.cx.tcx,
trait_def_id,
expected_args,
));
let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
self.cx.tcx,
trait_def_id,
actual_args,

View file

@ -495,9 +495,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
let res = {
// If `f` panics, `finish_diagnostics` will run during
// unwinding because of the `defer`.
let mut guar = None;
let sess_abort_guard = defer(|| {
guar = compiler.sess.finish_diagnostics(&config.registry);
compiler.sess.finish_diagnostics(&config.registry);
});
let res = f(&compiler);
@ -506,16 +505,14 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
// normally when `sess_abort_guard` is dropped.
drop(sess_abort_guard);
// If `finish_diagnostics` emits errors (e.g. stashed
// errors) we can't return an error directly, because the
// return type of this function is `R`, not `Result<R, E>`.
// But we need to communicate the errors' existence to the
// caller, otherwise the caller might mistakenly think that
// no errors occurred and return a zero exit code. So we
// abort (panic) instead, similar to if `f` had panicked.
if guar.is_some() {
compiler.sess.dcx().abort_if_errors();
}
// If error diagnostics have been emitted, we can't return an
// error directly, because the return type of this function
// is `R`, not `Result<R, E>`. But we need to communicate the
// errors' existence to the caller, otherwise the caller might
// mistakenly think that no errors occurred and return a zero
// exit code. So we abort (panic) instead, similar to if `f`
// had panicked.
compiler.sess.dcx().abort_if_errors();
res
};

View file

@ -8,7 +8,7 @@
mod callbacks;
mod errors;
pub mod interface;
mod passes;
pub mod passes;
mod proc_macro_decls;
mod queries;
pub mod util;

View file

@ -7,16 +7,16 @@ use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{Lrc, OnceLock, WorkerLocal};
use rustc_errors::PResult;
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features;
use rustc_fs_util::try_canonicalize;
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers;
use rustc_parse::{
@ -28,6 +28,7 @@ use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::filename_for_input;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};
@ -39,20 +40,22 @@ use std::any::Any;
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use std::sync::{Arc, LazyLock};
use std::{env, fs, iter};
use tracing::{info, instrument};
pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
let krate = sess.time("parse_crate", || {
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
Input::Str { input, name } => {
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
}
});
parser.parse_crate_mod()
})?;
pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
let krate = sess
.time("parse_crate", || {
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
Input::Str { input, name } => {
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
}
});
parser.parse_crate_mod()
})
.map_err(|parse_error| parse_error.emit())?;
if sess.opts.unstable_opts.input_stats {
eprintln!("Lines of code: {}", sess.source_map().count_lines());
@ -559,7 +562,7 @@ fn resolver_for_lowering_raw<'tcx>(
(tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
}
pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) {
pub fn write_dep_info(tcx: TyCtxt<'_>) {
// Make sure name resolution and macro expansion is run for
// the side-effect of providing a complete set of all
// accessed files and env vars.
@ -640,22 +643,48 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
*providers
});
pub fn create_global_ctxt<'tcx>(
pub(crate) fn create_global_ctxt<'tcx>(
compiler: &'tcx Compiler,
crate_types: Vec<CrateType>,
stable_crate_id: StableCrateId,
dep_graph: DepGraph,
untracked: Untracked,
mut krate: rustc_ast::Crate,
gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
) -> &'tcx GlobalCtxt<'tcx> {
) -> Result<&'tcx GlobalCtxt<'tcx>> {
let sess = &compiler.sess;
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.psess,
&sess.opts.unstable_opts.crate_attr,
);
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess)?;
let cstore =
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
let untracked =
Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids };
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
// incr. comp. yet.
dep_graph.assert_ignored();
let sess = &compiler.sess;
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
let codegen_backend = &compiler.codegen_backend;
@ -669,7 +698,7 @@ pub fn create_global_ctxt<'tcx>(
let incremental = dep_graph.is_fully_enabled();
sess.time("setup_global_ctxt", || {
gcx_cell.get_or_init(move || {
let qcx = gcx_cell.get_or_init(move || {
TyCtxt::create_global_ctxt(
sess,
crate_types,
@ -688,7 +717,23 @@ pub fn create_global_ctxt<'tcx>(
providers.hooks,
compiler.current_gcx.clone(),
)
})
});
qcx.enter(|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
feed.crate_name(crate_name);
let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
sess,
&pre_configured_attrs,
crate_name,
)));
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
feed.output_filenames(Arc::new(outputs));
});
Ok(qcx)
})
}
@ -924,12 +969,56 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
Ok(())
}
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
/// to write UI tests that actually test that compilation succeeds without reporting
/// an error.
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
match attr.meta_item_list() {
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
Some(list)
if list.iter().any(|list_item| {
matches!(
list_item.ident().map(|i| i.name),
Some(sym::delayed_bug_from_inside_query)
)
}) =>
{
tcx.ensure().trigger_delayed_bug(def_id);
}
// Bare `#[rustc_error]`.
None => {
tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) });
}
// Some other attribute.
Some(_) => {
tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation {
span: tcx.def_span(def_id),
});
}
}
}
}
/// Runs the codegen backend, after which the AST and analysis can
/// be discarded.
pub fn start_codegen<'tcx>(
pub(crate) fn start_codegen<'tcx>(
codegen_backend: &dyn CodegenBackend,
tcx: TyCtxt<'tcx>,
) -> Box<dyn Any> {
) -> Result<Box<dyn Any>> {
// Don't do code generation if there were any errors. Likewise if
// there were any delayed bugs, because codegen will likely cause
// more ICEs, obscuring the original problem.
if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() {
return Err(guar);
}
// Hook for UI tests.
check_for_rustc_errors_attr(tcx);
info!("Pre-codegen\n{:?}", tcx.debug_stats());
let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
@ -952,7 +1041,7 @@ pub fn start_codegen<'tcx>(
}
}
codegen
Ok(codegen)
}
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {

View file

@ -1,26 +1,20 @@
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
use crate::errors::FailedWritingFile;
use crate::interface::{Compiler, Result};
use crate::{errors, passes, util};
use crate::{errors, passes};
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
use rustc_metadata::creader::CStore;
use rustc_data_structures::sync::{OnceLock, WorkerLocal};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{GlobalCtxt, TyCtxt};
use rustc_serialize::opaque::FileEncodeResult;
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::config::{self, OutputFilenames, OutputType};
use rustc_session::Session;
use rustc_span::symbol::sym;
use std::any::Any;
use std::cell::{RefCell, RefMut};
use std::sync::Arc;
@ -106,133 +100,26 @@ impl<'tcx> Queries<'tcx> {
}
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
self.parse.compute(|| {
passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit())
})
self.parse.compute(|| passes::parse(&self.compiler.sess))
}
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
self.gcx.compute(|| {
let sess = &self.compiler.sess;
let krate = self.parse()?.steal();
let mut krate = self.parse()?.steal();
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.psess,
&sess.opts.unstable_opts.crate_attr,
);
let pre_configured_attrs =
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess)?;
let cstore = FreezeLock::new(Box::new(CStore::new(
self.compiler.codegen_backend.metadata_loader(),
)) as _);
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
let untracked = Untracked {
cstore,
source_span: AppendOnlyIndexVec::new(),
definitions,
stable_crate_ids,
};
let qcx = passes::create_global_ctxt(
passes::create_global_ctxt(
self.compiler,
crate_types,
stable_crate_id,
dep_graph,
untracked,
krate,
&self.gcx_cell,
&self.arena,
&self.hir_arena,
);
qcx.enter(|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
feed.crate_name(crate_name);
let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
sess,
&pre_configured_attrs,
crate_name,
)));
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
feed.output_filenames(Arc::new(outputs));
});
Ok(qcx)
)
})
}
pub fn write_dep_info(&'tcx self) -> Result<()> {
self.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
Ok(())
}
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
/// to write UI tests that actually test that compilation succeeds without reporting
/// an error.
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
match attr.meta_item_list() {
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
Some(list)
if list.iter().any(|list_item| {
matches!(
list_item.ident().map(|i| i.name),
Some(sym::delayed_bug_from_inside_query)
)
}) =>
{
tcx.ensure().trigger_delayed_bug(def_id);
}
// Bare `#[rustc_error]`.
None => {
tcx.dcx().emit_fatal(RustcErrorFatal { span: tcx.def_span(def_id) });
}
// Some other attribute.
Some(_) => {
tcx.dcx()
.emit_warn(RustcErrorUnexpectedAnnotation { span: tcx.def_span(def_id) });
}
}
}
}
pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> {
self.global_ctxt()?.enter(|tcx| {
// Don't do code generation if there were any errors. Likewise if
// there were any delayed bugs, because codegen will likely cause
// more ICEs, obscuring the original problem.
if let Some(guar) = self.compiler.sess.dcx().has_errors_or_delayed_bugs() {
return Err(guar);
}
// Hook for UI tests.
Self::check_for_rustc_errors_attr(tcx);
let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx);
let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx)?;
Ok(Linker {
dep_graph: tcx.dep_graph.clone(),

View file

@ -604,6 +604,9 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
.suggestion = use pat_param to preserve semantics
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope
.help = import `macro_rules` with `use` to make it callable above its definition
lint_overflowing_bin_hex = literal out of range for `{$ty}`
.negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`

View file

@ -434,5 +434,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
lints::InnerAttributeUnstable::CustomInnerAttribute
}
.decorate_lint(diag),
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
}
}
}

View file

@ -2911,3 +2911,10 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
#[suggestion_part(code = ")")]
pub right: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_out_of_scope_macro_calls)]
#[help]
pub struct OutOfScopeMacroCalls {
pub path: String,
}

View file

@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
return;
}
let proj_ty = Ty::new_projection(
let proj_ty = Ty::new_projection_from_args(
cx.tcx,
proj.projection_term.def_id,
proj.projection_term.args,

View file

@ -4945,3 +4945,42 @@ declare_lint! {
reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
};
}
declare_lint! {
/// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope,
/// above their definition, which may happen in key-value attributes.
///
/// ### Example
///
/// ```rust
/// #![doc = in_root!()]
///
/// macro_rules! in_root { () => { "" } }
///
/// fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The scope in which a `macro_rules` item is visible starts at that item and continues
/// below it. This is more similar to `let` than to other items, which are in scope both above
/// and below their definition.
/// Due to a bug `macro_rules` were accidentally in scope inside some key-value attributes
/// above their definition. The lint catches such cases.
/// To address the issue turn the `macro_rules` into a regularly scoped item by importing it
/// with `use`.
///
/// This is a [future-incompatible] lint to transition this to a
/// hard error in the future.
///
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub OUT_OF_SCOPE_MACRO_CALLS,
Warn,
"detects out of scope calls to `macro_rules` in key-value attributes",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #124535 <https://github.com/rust-lang/rust/issues/124535>",
};
}

View file

@ -744,6 +744,9 @@ pub enum BuiltinLintDiag {
InnerAttributeUnstable {
is_macro: bool,
},
OutOfScopeMacroCalls {
path: String,
},
}
/// Lints that are buffered up early on in the `Session` before the

View file

@ -1817,11 +1817,11 @@ mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 144);
static_assert_size!(BasicBlockData<'_>, 128);
static_assert_size!(LocalDecl<'_>, 40);
static_assert_size!(SourceScopeData<'_>, 64);
static_assert_size!(Statement<'_>, 32);
static_assert_size!(Terminator<'_>, 112);
static_assert_size!(Terminator<'_>, 96);
static_assert_size!(VarDebugInfo<'_>, 88);
// tidy-alphabetical-end
}

View file

@ -730,7 +730,7 @@ pub enum TerminatorKind<'tcx> {
/// reused across function calls without duplicating the contents.
/// The span for each arg is also included
/// (e.g. `a` and `b` in `x.foo(a, b)`).
args: Vec<Spanned<Operand<'tcx>>>,
args: Box<[Spanned<Operand<'tcx>>]>,
/// Where the returned value will be written
destination: Place<'tcx>,
/// Where to go after this call returns. If none, the call necessarily diverges.
@ -837,7 +837,7 @@ pub enum TerminatorKind<'tcx> {
template: &'tcx [InlineAsmTemplatePiece],
/// The operands for the inline assembly, as `Operand`s or `Place`s.
operands: Vec<InlineAsmOperand<'tcx>>,
operands: Box<[InlineAsmOperand<'tcx>]>,
/// Miscellaneous options for the inline assembly.
options: InlineAsmOptions,
@ -849,7 +849,7 @@ pub enum TerminatorKind<'tcx> {
/// Valid targets for the inline assembly.
/// The first element is the fallthrough destination, unless
/// InlineAsmOptions::NORETURN is set.
targets: Vec<BasicBlock>,
targets: Box<[BasicBlock]>,
/// Action to be taken if the inline assembly unwinds. This is present
/// if and only if InlineAsmOptions::MAY_UNWIND is set.
@ -1561,6 +1561,6 @@ mod size_asserts {
static_assert_size!(PlaceElem<'_>, 24);
static_assert_size!(Rvalue<'_>, 40);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(TerminatorKind<'_>, 96);
static_assert_size!(TerminatorKind<'_>, 80);
// tidy-alphabetical-end
}

View file

@ -240,7 +240,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
let trait_generics = self.generics_of(trait_def_id);
(
ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)),
ty::TraitRef::new_from_args(self, trait_def_id, args.truncate_to(self, trait_generics)),
&args[trait_generics.count()..],
)
}
@ -261,12 +261,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.check_args_compatible(def_id, args)
}
fn check_and_mk_args(
self,
def_id: DefId,
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
) -> ty::GenericArgsRef<'tcx> {
self.check_and_mk_args(def_id, args)
fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) {
self.debug_assert_args_compatible(def_id, args);
}
fn intern_canonical_goal_evaluation_step(

View file

@ -309,7 +309,8 @@ impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
#[derive(Copy, Clone, Debug)]
pub enum SizeSkeleton<'tcx> {
/// Any statically computable Layout.
Known(Size),
/// Alignment can be `None` if unknown.
Known(Size, Option<Align>),
/// This is a generic const expression (i.e. N * 2), which may contain some parameters.
/// It must be of type usize, and represents the size of a type in bytes.
@ -339,7 +340,12 @@ impl<'tcx> SizeSkeleton<'tcx> {
// First try computing a static layout.
let err = match tcx.layout_of(param_env.and(ty)) {
Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size));
if layout.abi.is_sized() {
return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
} else {
// Just to be safe, don't claim a known layout for unsized types.
return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
}
}
Err(err @ LayoutError::Unknown(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
@ -389,19 +395,20 @@ impl<'tcx> SizeSkeleton<'tcx> {
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
let len_eval = len.try_eval_target_usize(tcx, param_env);
if len_eval == Some(0) {
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
}
match SizeSkeleton::compute(inner, tcx, param_env)? {
// This may succeed because the multiplication of two types may overflow
// but a single size of a nested array will not.
SizeSkeleton::Known(s) => {
SizeSkeleton::Known(s, a) => {
if let Some(c) = len_eval {
let size = s
.bytes()
.checked_mul(c)
.ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
// Alignment is unchanged by arrays.
return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
}
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
}
@ -427,8 +434,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
for field in fields {
let field = field?;
match field {
SizeSkeleton::Known(size) => {
if size.bytes() > 0 {
SizeSkeleton::Known(size, align) => {
let is_1zst = size.bytes() == 0
&& align.is_some_and(|align| align.bytes() == 1);
if !is_1zst {
return Err(err);
}
}
@ -492,7 +501,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
match (self, other) {
(SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
(SizeSkeleton::Known(a, _), SizeSkeleton::Known(b, _)) => a == b,
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
a == b
}

View file

@ -133,6 +133,20 @@ impl<H, T> RawList<H, T> {
}
}
impl<'a, H, T: Copy> rustc_type_ir::inherent::SliceLike for &'a RawList<H, T> {
type Item = T;
type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
fn iter(self) -> Self::IntoIter {
(*self).iter()
}
fn as_slice(&self) -> &[Self::Item] {
(*self).as_slice()
}
}
macro_rules! impl_list_empty {
($header_ty:ty, $header_init:expr) => {
impl<T> RawList<$header_ty, T> {

View file

@ -499,7 +499,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args))
Ty::new_alias(tcx, ty::Opaque, AliasTy::new_from_args(tcx, def_id, args))
}
/// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
@ -669,6 +669,15 @@ impl<'tcx> Ty<'tcx> {
Ty::new(tcx, Dynamic(obj, reg, repr))
}
#[inline]
pub fn new_projection_from_args(
tcx: TyCtxt<'tcx>,
item_def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
) -> Ty<'tcx> {
Ty::new_alias(tcx, ty::Projection, AliasTy::new_from_args(tcx, item_def_id, args))
}
#[inline]
pub fn new_projection(
tcx: TyCtxt<'tcx>,
@ -1409,7 +1418,7 @@ impl<'tcx> Ty<'tcx> {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
}
ty::Pat(ty, _) => ty.discriminant_ty(tcx),

View file

@ -170,7 +170,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
.map(|arg|
Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } )
)
.collect::<PResult<Vec<_>>>()?;
.collect::<PResult<Box<[_]>>>()?;
Ok(TerminatorKind::Call {
func: fun,
args,

View file

@ -152,10 +152,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_info,
TerminatorKind::Call {
func: exchange_malloc,
args: vec![
args: [
Spanned { node: Operand::Move(size), span: DUMMY_SP },
Spanned { node: Operand::Move(align), span: DUMMY_SP },
],
]
.into(),
destination: storage,
target: Some(success),
unwind: UnwindAction::Continue,

View file

@ -238,7 +238,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
let fun = unpack!(block = this.as_local_operand(block, fun));
let args: Vec<_> = args
let args: Box<[_]> = args
.into_iter()
.copied()
.map(|arg| Spanned {
@ -485,7 +485,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
operands,
options,
line_spans,
targets,
targets: targets.into_boxed_slice(),
unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
UnwindAction::Continue
} else {

View file

@ -324,7 +324,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: None,
const_: method,
})),
args: vec![Spanned { node: Operand::Move(ref_src), span }],
args: [Spanned { node: Operand::Move(ref_src), span }].into(),
destination: temp,
target: Some(target_block),
unwind: UnwindAction::Continue,
@ -486,10 +486,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
const_: method,
})),
args: vec![
args: [
Spanned { node: Operand::Copy(val), span: DUMMY_SP },
Spanned { node: expect, span: DUMMY_SP },
],
]
.into(),
destination: eq_result,
target: Some(eq_block),
unwind: UnwindAction::Continue,

View file

@ -220,7 +220,7 @@ impl<'tcx> ConstToPat<'tcx> {
tcx,
ObligationCause::dummy(),
self.param_env,
ty::TraitRef::new(
ty::TraitRef::new_from_args(
tcx,
partial_eq_trait_id,
tcx.with_opt_host_effect_param(

View file

@ -650,10 +650,8 @@ where
[ty.into()],
self.source_info.span,
),
args: vec![Spanned {
node: Operand::Move(Place::from(ref_place)),
span: DUMMY_SP,
}],
args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }]
.into(),
destination: unit_temp,
target: Some(succ),
unwind: unwind.into_action(),

View file

@ -34,7 +34,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
2,
mir::TerminatorKind::Call {
func: mir::Operand::Copy(dummy_place.clone()),
args: vec![],
args: [].into(),
destination: dummy_place.clone(),
target: Some(mir::START_BLOCK),
unwind: mir::UnwindAction::Continue,
@ -48,7 +48,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
4,
mir::TerminatorKind::Call {
func: mir::Operand::Copy(dummy_place.clone()),
args: vec![],
args: [].into(),
destination: dummy_place.clone(),
target: Some(mir::START_BLOCK),
unwind: mir::UnwindAction::Continue,

View file

@ -677,8 +677,8 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local {
let terminator = bb_data.terminator.take().unwrap();
if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind {
let arg = args.pop().unwrap();
if let TerminatorKind::Call { args, destination, target, .. } = terminator.kind {
let [arg] = *Box::try_from(args).unwrap();
let local = arg.node.place().unwrap().local;
let arg = Rvalue::Use(arg.node);

View file

@ -134,7 +134,7 @@ impl<'tcx> MockBlocks<'tcx> {
some_from_block,
TerminatorKind::Call {
func: Operand::Copy(self.dummy_place.clone()),
args: vec![],
args: [].into(),
destination: self.dummy_place.clone(),
target: Some(TEMP_BLOCK),
unwind: UnwindAction::Continue,

View file

@ -624,8 +624,7 @@ impl<'tcx> Inliner<'tcx> {
};
// Copy the arguments if needed.
let args: Vec<_> =
self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
let mut integrator = Integrator {
args: &args,
@ -736,12 +735,12 @@ impl<'tcx> Inliner<'tcx> {
fn make_call_args(
&self,
args: Vec<Spanned<Operand<'tcx>>>,
args: Box<[Spanned<Operand<'tcx>>]>,
callsite: &CallSite<'tcx>,
caller_body: &mut Body<'tcx>,
callee_body: &Body<'tcx>,
return_block: Option<BasicBlock>,
) -> Vec<Local> {
) -> Box<[Local]> {
let tcx = self.tcx;
// There is a bit of a mismatch between the *caller* of a closure and the *callee*.
@ -768,7 +767,8 @@ impl<'tcx> Inliner<'tcx> {
//
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
let mut args = args.into_iter();
// FIXME(edition_2024): switch back to a normal method call.
let mut args = <_>::into_iter(args);
let self_ = self.create_temp_if_necessary(
args.next().unwrap().node,
callsite,
@ -802,7 +802,8 @@ impl<'tcx> Inliner<'tcx> {
closure_ref_arg.chain(tuple_tmp_args).collect()
} else {
args.into_iter()
// FIXME(edition_2024): switch back to a normal method call.
<_>::into_iter(args)
.map(|a| self.create_temp_if_necessary(a.node, callsite, caller_body, return_block))
.collect()
}

View file

@ -1,6 +1,7 @@
//! Performs various peephole optimizations.
use crate::simplify::simplify_duplicate_switch_targets;
use crate::take_array;
use rustc_ast::attr;
use rustc_middle::bug;
use rustc_middle::mir::*;
@ -285,7 +286,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
return;
}
let Some(arg_place) = args.pop().unwrap().node.place() else { return };
let Ok([arg]) = take_array(args) else { return };
let Some(arg_place) = arg.node.place() else { return };
statements.push(Statement {
source_info: terminator.source_info,

View file

@ -160,8 +160,9 @@ fn remap_mir_for_const_eval_select<'tcx>(
} if let ty::FnDef(def_id, _) = *const_.ty().kind()
&& tcx.is_intrinsic(def_id, sym::const_eval_select) =>
{
let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
std::mem::take(args).try_into().unwrap();
let Ok([tupled_args, called_in_const, called_at_rt]) = take_array(args) else {
unreachable!()
};
let ty = tupled_args.node.ty(&body.local_decls, tcx);
let fields = ty.tuple_fields();
let num_args = fields.len();
@ -211,6 +212,11 @@ fn remap_mir_for_const_eval_select<'tcx>(
body
}
fn take_array<T, const N: usize>(b: &mut Box<[T]>) -> Result<[T; N], Box<[T]>> {
let b: Box<[T; N]> = std::mem::take(b).try_into()?;
Ok(*b)
}
fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
tcx.mir_keys(()).contains(&def_id)
}

View file

@ -1,5 +1,6 @@
//! Lowers intrinsic calls
use crate::take_array;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{bug, span_bug};
@ -50,42 +51,34 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
sym::copy_nonoverlapping => {
let target = target.unwrap();
let mut args = args.drain(..);
let Ok([src, dst, count]) = take_array(args) else {
bug!("Wrong arguments for copy_non_overlapping intrinsic");
};
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Intrinsic(Box::new(
NonDivergingIntrinsic::CopyNonOverlapping(
rustc_middle::mir::CopyNonOverlapping {
src: args.next().unwrap().node,
dst: args.next().unwrap().node,
count: args.next().unwrap().node,
src: src.node,
dst: dst.node,
count: count.node,
},
),
)),
});
assert_eq!(
args.next(),
None,
"Extra argument for copy_non_overlapping intrinsic"
);
drop(args);
terminator.kind = TerminatorKind::Goto { target };
}
sym::assume => {
let target = target.unwrap();
let mut args = args.drain(..);
let Ok([arg]) = take_array(args) else {
bug!("Wrong arguments for assume intrinsic");
};
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Intrinsic(Box::new(
NonDivergingIntrinsic::Assume(args.next().unwrap().node),
NonDivergingIntrinsic::Assume(arg.node),
)),
});
assert_eq!(
args.next(),
None,
"Extra argument for copy_non_overlapping intrinsic"
);
drop(args);
terminator.kind = TerminatorKind::Goto { target };
}
sym::wrapping_add
@ -100,13 +93,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
| sym::unchecked_shl
| sym::unchecked_shr => {
let target = target.unwrap();
let lhs;
let rhs;
{
let mut args = args.drain(..);
lhs = args.next().unwrap();
rhs = args.next().unwrap();
}
let Ok([lhs, rhs]) = take_array(args) else {
bug!("Wrong arguments for {} intrinsic", intrinsic.name);
};
let bin_op = match intrinsic.name {
sym::wrapping_add => BinOp::Add,
sym::wrapping_sub => BinOp::Sub,
@ -132,13 +121,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
if let Some(target) = *target {
let lhs;
let rhs;
{
let mut args = args.drain(..);
lhs = args.next().unwrap();
rhs = args.next().unwrap();
}
let Ok([lhs, rhs]) = take_array(args) else {
bug!("Wrong arguments for {} intrinsic", intrinsic.name);
};
let bin_op = match intrinsic.name {
sym::add_with_overflow => BinOp::AddWithOverflow,
sym::sub_with_overflow => BinOp::SubWithOverflow,
@ -174,7 +159,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
}
sym::read_via_copy => {
let [arg] = args.as_slice() else {
let Ok([arg]) = take_array(args) else {
span_bug!(terminator.source_info.span, "Wrong number of arguments");
};
let derefed_place = if let Some(place) = arg.node.place()
@ -207,7 +192,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
sym::write_via_move => {
let target = target.unwrap();
let Ok([ptr, val]) = <[_; 2]>::try_from(std::mem::take(args)) else {
let Ok([ptr, val]) = take_array(args) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for write_via_move intrinsic",
@ -247,7 +232,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
sym::offset => {
let target = target.unwrap();
let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
let Ok([ptr, delta]) = take_array(args) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for offset intrinsic",
@ -264,7 +249,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
sym::transmute | sym::transmute_unchecked => {
let dst_ty = destination.ty(local_decls, tcx).ty;
let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
let Ok([arg]) = take_array(args) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for transmute intrinsic",
@ -289,7 +274,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
}
sym::aggregate_raw_ptr => {
let Ok([data, meta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
let Ok([data, meta]) = take_array(args) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for aggregate_raw_ptr intrinsic",
@ -317,7 +302,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Goto { target };
}
sym::ptr_metadata => {
let Ok([ptr]) = <[_; 1]>::try_from(std::mem::take(args)) else {
let Ok([ptr]) = take_array(args) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for ptr_metadata intrinsic",

View file

@ -562,7 +562,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
vec![statement],
TerminatorKind::Call {
func,
args: vec![Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }],
args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
destination: dest,
target: Some(next),
unwind: UnwindAction::Cleanup(cleanup),
@ -843,7 +843,7 @@ fn build_call_shim<'tcx>(
};
// BB #0
let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect::<Vec<_>>();
let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
block(
&mut blocks,
statements,

View file

@ -527,7 +527,7 @@ where
};
for assumption in
self.cx().item_bounds(alias_ty.def_id).iter_instantiated(self.cx(), &alias_ty.args)
self.cx().item_bounds(alias_ty.def_id).iter_instantiated(self.cx(), alias_ty.args)
{
candidates.extend(G::probe_and_consider_implied_clause(
self,
@ -603,7 +603,7 @@ where
// Consider all of the auto-trait and projection bounds, which don't
// need to be recorded as a `BuiltinImplSource::Object` since they don't
// really have a vtable base...
for bound in bounds {
for bound in bounds.iter() {
match bound.skip_binder() {
ty::ExistentialPredicate::Trait(_) => {
// Skip principal

View file

@ -58,7 +58,7 @@ where
ty::Tuple(tys) => {
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
Ok(tys.into_iter().map(ty::Binder::dummy).collect())
Ok(tys.iter().map(ty::Binder::dummy).collect())
}
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
@ -79,23 +79,21 @@ where
.cx()
.bound_coroutine_hidden_types(def_id)
.into_iter()
.map(|bty| bty.instantiate(tcx, &args))
.map(|bty| bty.instantiate(tcx, args))
.collect()),
// For `PhantomData<T>`, we pass `T`.
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
ty::Adt(def, args) => Ok(def
.all_field_tys(tcx)
.iter_instantiated(tcx, &args)
.map(ty::Binder::dummy)
.collect()),
ty::Adt(def, args) => {
Ok(def.all_field_tys(tcx).iter_instantiated(tcx, args).map(ty::Binder::dummy).collect())
}
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, &args))])
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))])
}
}
}
@ -147,7 +145,7 @@ where
// impl Sized for ()
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |&ty| vec![ty::Binder::dummy(ty)])),
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])),
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
@ -160,7 +158,7 @@ where
// if the ADT is sized for all possible args.
ty::Adt(def, args) => {
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), &args))])
Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), args))])
} else {
Ok(vec![])
}
@ -213,7 +211,7 @@ where
}
// impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
ty::Tuple(tys) => Ok(tys.into_iter().map(ty::Binder::dummy).collect()),
ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
@ -242,7 +240,7 @@ where
.cx()
.bound_coroutine_hidden_types(def_id)
.into_iter()
.map(|bty| bty.instantiate(ecx.cx(), &args))
.map(|bty| bty.instantiate(ecx.cx(), args))
.collect()),
}
}
@ -259,8 +257,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
let sig = tcx.fn_sig(def_id);
if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) {
Ok(Some(
sig.instantiate(tcx, &args)
.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output())),
sig.instantiate(tcx, args)
.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
))
} else {
Err(NoSolution)
@ -269,7 +267,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
ty::FnPtr(sig) => {
if sig.is_fn_trait_compatible() {
Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output()))))
Ok(Some(
sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
))
} else {
Err(NoSolution)
}
@ -292,7 +292,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
}
}
}
Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
Ok(Some(
closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
))
}
// Coroutine-closures don't implement `Fn` traits the normal way.
@ -470,7 +472,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
tupled_inputs_ty: Ty::new_tup(tcx, &sig.inputs()),
tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs().as_slice()),
output_coroutine_ty: sig.output(),
coroutine_return_ty: future_output_ty,
}),
@ -521,7 +523,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
Ok((
bound_sig.rebind(AsyncCallableRelevantTypes {
tupled_inputs_ty: sig.inputs()[0],
tupled_inputs_ty: sig.inputs().get(0).unwrap(),
output_coroutine_ty: sig.output(),
coroutine_return_ty: future_output_ty,
}),
@ -669,7 +671,7 @@ where
let tcx = ecx.cx();
let mut requirements = vec![];
requirements
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args));
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, trait_ref.args));
// FIXME(associated_const_equality): Also add associated consts to
// the requirements here.
@ -680,13 +682,12 @@ where
continue;
}
requirements.extend(
tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, &trait_ref.args),
);
requirements
.extend(tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, trait_ref.args));
}
let mut replace_projection_with = HashMap::default();
for bound in object_bounds {
for bound in object_bounds.iter() {
if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));

View file

@ -267,7 +267,9 @@ where
// 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 = IndexVec::from_elem_n(None, response.variables.len());
for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
for (original_value, result_value) in
iter::zip(original_values, var_values.var_values.iter())
{
match result_value.kind() {
ty::GenericArgKind::Type(t) => {
if let ty::Bound(debruijn, b) = t.kind() {
@ -291,7 +293,7 @@ where
}
let var_values = delegate.cx().mk_args_from_iter(
response.variables.into_iter().enumerate().map(|(index, info)| {
response.variables.iter().enumerate().map(|(index, info)| {
if info.universe() != ty::UniverseIndex::ROOT {
// A variable from inside a binder of the query. While ideally these shouldn't
// exist at all (see the FIXME at the start of this method), we have to deal with
@ -344,7 +346,7 @@ where
) {
assert_eq!(original_values.len(), var_values.len());
for (&orig, response) in iter::zip(original_values, var_values.var_values) {
for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
let goals =
delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap();
assert!(goals.is_empty());
@ -413,7 +415,8 @@ where
// In case any fresh inference variables have been created between `state`
// and the previous instantiation, extend `orig_values` for it.
assert!(orig_values.len() <= state.value.var_values.len());
for &arg in &state.value.var_values.var_values[orig_values.len()..state.value.var_values.len()]
for &arg in &state.value.var_values.var_values.as_slice()
[orig_values.len()..state.value.var_values.len()]
{
// FIXME: This is so ugly.
let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span);

View file

@ -787,7 +787,7 @@ where
// Alternatively we could modify `Equate` for this case by adding another
// variant to `StructurallyRelateAliases`.
let identity_args = self.fresh_args_for_item(alias.def_id);
let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args);
let rigid_ctor = ty::AliasTerm::new_from_args(tcx, alias.def_id, identity_args);
let ctor_term = rigid_ctor.to_term(tcx);
let obligations =
self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
@ -875,7 +875,7 @@ where
pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
let args = self.delegate.fresh_args_for_item(def_id);
for arg in args {
for arg in args.iter() {
self.inspect.add_var_value(arg);
}
args
@ -979,7 +979,7 @@ where
result: *result,
})
.enter(|ecx| {
for (a, b) in std::iter::zip(candidate_key.args, key.args) {
for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) {
ecx.eq(param_env, a, b)?;
}
ecx.eq(param_env, candidate_ty, ty)?;

View file

@ -7,6 +7,7 @@
use std::marker::PhantomData;
use std::mem;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner};
use crate::delegate::SolverDelegate;

View file

@ -182,7 +182,7 @@ where
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
ty::ConstKind::Unevaluated(uv) => {
self.cx().type_of(uv.def).instantiate(self.cx(), &uv.args)
self.cx().type_of(uv.def).instantiate(self.cx(), uv.args)
}
ty::ConstKind::Expr(_) => unimplemented!(
"`feature(generic_const_exprs)` is not supported in the new trait solver"

View file

@ -29,7 +29,7 @@ where
self.eq(
goal.param_env,
inherent.self_ty(),
tcx.type_of(impl_def_id).instantiate(tcx, &impl_args),
tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
)?;
// Equate IAT with the RHS of the project goal
@ -44,11 +44,11 @@ where
self.add_goals(
GoalSource::Misc,
tcx.predicates_of(inherent.def_id)
.iter_instantiated(tcx, &inherent_args)
.iter_instantiated(tcx, inherent_args)
.map(|pred| goal.with(tcx, pred)),
);
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, &inherent_args);
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args);
self.instantiate_normalizes_to_term(goal, normalized.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}

View file

@ -121,7 +121,7 @@ where
ecx.add_goals(
GoalSource::Misc,
tcx.own_predicates_of(goal.predicate.def_id())
.iter_instantiated(tcx, &goal.predicate.alias.args)
.iter_instantiated(tcx, goal.predicate.alias.args)
.map(|pred| goal.with(tcx, pred)),
);
@ -163,13 +163,13 @@ where
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args);
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.iter_instantiated(tcx, &impl_args)
.iter_instantiated(tcx, impl_args)
.map(|pred| goal.with(tcx, pred));
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
@ -177,7 +177,7 @@ where
ecx.add_goals(
GoalSource::Misc,
tcx.own_predicates_of(goal.predicate.def_id())
.iter_instantiated(tcx, &goal.predicate.alias.args)
.iter_instantiated(tcx, goal.predicate.alias.args)
.map(|pred| goal.with(tcx, pred)),
);
@ -254,7 +254,7 @@ where
kind => panic!("expected projection, found {kind:?}"),
};
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, &target_args));
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, target_args));
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
@ -467,7 +467,7 @@ where
tupled_inputs_ty,
tupled_upvars_ty,
coroutine_captures_by_ref_ty,
] = **goal.predicate.alias.args
] = *goal.predicate.alias.args.as_slice()
else {
panic!();
};
@ -567,14 +567,14 @@ where
ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(tcx) {
None => Ty::new_unit(tcx),
Some(tail_ty) => {
Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, &args)])
Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, args)])
}
},
ty::Adt(_, _) => Ty::new_unit(tcx),
ty::Tuple(elements) => match elements.last() {
None => Ty::new_unit(tcx),
Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
Some(tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
},
ty::Infer(
@ -895,7 +895,7 @@ where
} else {
let target_args = self.fresh_args_for_item(target_container_def_id);
let target_trait_ref =
tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, &target_args);
tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, target_args);
// Relate source impl to target impl by equating trait refs.
self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
// Also add predicates since they may be needed to constrain the
@ -903,7 +903,7 @@ where
self.add_goals(
GoalSource::Misc,
tcx.predicates_of(target_container_def_id)
.iter_instantiated(tcx, &target_args)
.iter_instantiated(tcx, target_args)
.map(|pred| goal.with(tcx, pred)),
);
goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args)

View file

@ -86,7 +86,7 @@ where
}
(Reveal::All, _) => {
// FIXME: Add an assertion that opaque type storage is empty.
let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, &opaque_ty.args);
let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args);
self.eq(goal.param_env, expected, actual)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
@ -102,7 +102,7 @@ pub fn uses_unique_placeholders_ignoring_regions<I: Interner>(
args: I::GenericArgs,
) -> Result<(), NotUniqueParam<I>> {
let mut seen = GrowableBitSet::default();
for arg in args {
for arg in args.iter() {
match arg.kind() {
// Ignore regions, since we can't resolve those in a canonicalized
// query in the trait solver.

View file

@ -25,11 +25,11 @@ where
self.add_goals(
GoalSource::Misc,
tcx.predicates_of(weak_ty.def_id)
.iter_instantiated(tcx, &weak_ty.args)
.iter_instantiated(tcx, weak_ty.args)
.map(|pred| goal.with(tcx, pred)),
);
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, &weak_ty.args);
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
self.instantiate_normalizes_to_term(goal, actual.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)

View file

@ -77,12 +77,12 @@ where
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id);
ecx.record_impl_args(impl_args);
let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args);
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.iter_instantiated(tcx, &impl_args)
.iter_instantiated(tcx, impl_args)
.map(|pred| goal.with(tcx, pred));
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
@ -186,7 +186,7 @@ where
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let nested_obligations = tcx
.predicates_of(goal.predicate.def_id())
.iter_instantiated(tcx, &goal.predicate.trait_ref.args)
.iter_instantiated(tcx, goal.predicate.trait_ref.args)
.map(|p| goal.with(tcx, p));
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
ecx.add_goals(GoalSource::Misc, nested_obligations);
@ -373,7 +373,7 @@ where
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
panic!();
};
@ -783,7 +783,7 @@ where
// (i.e. the principal, all of the associated types match, and any auto traits)
ecx.add_goals(
GoalSource::ImplWhereBound,
b_data.into_iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
);
// The type must be `Sized` to be unsized.
@ -851,7 +851,7 @@ where
};
self.probe_trait_candidate(source).enter(|ecx| {
for bound in b_data {
for bound in b_data.iter() {
match bound.skip_binder() {
// Check that a's supertrait (upcast_principal) is compatible
// with the target (b_ty).
@ -953,18 +953,15 @@ where
let tail_field_ty = def.struct_tail_ty(tcx).unwrap();
let a_tail_ty = tail_field_ty.instantiate(tcx, &a_args);
let b_tail_ty = tail_field_ty.instantiate(tcx, &b_args);
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
// Instantiate just the unsizing params from B into A. The type after
// this instantiation must be equal to B. This is so we don't unsize
// unrelated type parameters.
let new_a_args = tcx.mk_args_from_iter(
a_args
.iter()
.enumerate()
.map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { *a }),
);
let new_a_args = tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
}));
let unsized_a_ty = Ty::new_adt(tcx, def, new_a_args);
// Finally, we require that `TailA: Unsize<TailB>` for the tail field
@ -1005,7 +1002,7 @@ where
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
let &b_last_ty = b_tys.last().unwrap();
let b_last_ty = b_tys.last().unwrap();
// Instantiate just the tail field of B., and require that they're equal.
let unsized_a_ty =

View file

@ -322,9 +322,8 @@ error: foo
--> test.rs:3:3
|
3 | X0 Y0
| ___^__-
| |___|
| ||
| ____^ -
| | ______|
4 | || X1 Y1
5 | || X2 Y2
| ||____^__- `Y` is a good letter too
@ -361,9 +360,8 @@ error: foo
--> test.rs:3:3
|
3 | X0 Y0
| ___^__-
| |___|
| ||
| ____^ -
| | ______|
4 | || Y1 X1
| ||____-__^ `X` is a good letter
| |____|
@ -445,10 +443,9 @@ error: foo
--> test.rs:3:3
|
3 | X0 Y0 Z0
| ___^__-__-
| |___|__|
| ||___|
| |||
| _____^ - -
| | _______| |
| || _________|
4 | ||| X1 Y1 Z1
5 | ||| X2 Y2 Z2
| |||____^__-__- `Z` label

View file

@ -4,8 +4,10 @@ use crate::{errors, parse_in};
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::MetaItemKind;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
use rustc_ast::{
self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemKind,
NestedMetaItem, Safety,
};
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{
AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
@ -184,9 +186,13 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
let is_one_allowed_subword = |items: &[NestedMetaItem]| match items {
[item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)),
_ => false,
};
match meta {
MetaItemKind::Word => template.word,
MetaItemKind::List(..) => template.list.is_some(),
MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items),
MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(),
MetaItemKind::NameValue(..) => false,
}
@ -230,6 +236,7 @@ fn emit_malformed_attribute(
if let Some(descr) = template.list {
suggestions.push(format!("#{inner}[{name}({descr})]"));
}
suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
if let Some(descr) = template.name_value_str {
suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
}

View file

@ -103,18 +103,9 @@ passes_continue_labeled_block =
.label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to
passes_coverage_fn_defn =
`#[coverage]` may only be applied to function definitions
passes_coverage_ignored_function_prototype =
`#[coverage]` is ignored on function prototypes
passes_coverage_not_coverable =
`#[coverage]` must be applied to coverable code
.label = not coverable code
passes_coverage_propagate =
`#[coverage]` does not propagate into items and must be applied to the contained functions directly
passes_coverage_not_fn_or_closure =
attribute should be applied to a function definition or closure
.label = not a function or closure
passes_dead_codes =
{ $multiple ->

View file

@ -122,7 +122,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
}
[sym::inline] => self.check_inline(hir_id, attr, span, target),
[sym::coverage] => self.check_coverage(hir_id, attr, span, target),
[sym::coverage] => self.check_coverage(attr, span, target),
[sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target),
[sym::marker] => self.check_marker(hir_id, attr, span, target),
[sym::target_feature] => {
@ -369,47 +369,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
/// Checks if a `#[coverage]` is applied directly to a function
fn check_coverage(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
/// Checks that `#[coverage(..)]` is applied to a function or closure.
fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
// #[coverage] on function is fine
// #[coverage(..)] on function is fine
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// function prototypes can't be covered
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredCoverageFnProto,
);
true
}
Target::Mod | Target::ForeignMod | Target::Impl | Target::Trait => {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredCoveragePropagate,
);
true
}
Target::Expression | Target::Statement | Target::Arm => {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredCoverageFnDefn,
);
true
}
_ => {
self.dcx().emit_err(errors::IgnoredCoverageNotCoverable {
self.dcx().emit_err(errors::CoverageNotFnOrClosure {
attr_span: attr.span,
defn_span: span,
});

View file

@ -1010,6 +1010,22 @@ impl<'tcx> DeadVisitor<'tcx> {
parent_item: Option<LocalDefId>,
report_on: ReportOn,
) {
fn get_parent_if_enum_variant<'tcx>(
tcx: TyCtxt<'tcx>,
may_variant: LocalDefId,
) -> LocalDefId {
if let Node::Variant(_) = tcx.hir_node_by_def_id(may_variant)
&& let Some(enum_did) = tcx.opt_parent(may_variant.to_def_id())
&& let Some(enum_local_id) = enum_did.as_local()
&& let Node::Item(item) = tcx.hir_node_by_def_id(enum_local_id)
&& let ItemKind::Enum(_, _) = item.kind
{
enum_local_id
} else {
may_variant
}
}
let Some(&first_item) = dead_codes.first() else {
return;
};
@ -1053,6 +1069,9 @@ impl<'tcx> DeadVisitor<'tcx> {
};
let encl_def_id = parent_item.unwrap_or(first_item.def_id);
// If parent of encl_def_id is an enum, use the parent ID intead.
let encl_def_id = get_parent_if_enum_variant(tcx, encl_def_id);
let ignored_derived_impls =
if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
let trait_list = ign_traits

View file

@ -60,21 +60,9 @@ pub struct InlineNotFnOrClosure {
pub defn_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(passes_coverage_ignored_function_prototype)]
pub struct IgnoredCoverageFnProto;
#[derive(LintDiagnostic)]
#[diag(passes_coverage_propagate)]
pub struct IgnoredCoveragePropagate;
#[derive(LintDiagnostic)]
#[diag(passes_coverage_fn_defn)]
pub struct IgnoredCoverageFnDefn;
#[derive(Diagnostic)]
#[diag(passes_coverage_not_coverable, code = E0788)]
pub struct IgnoredCoverageNotCoverable {
#[diag(passes_coverage_not_fn_or_closure, code = E0788)]
pub struct CoverageNotFnOrClosure {
#[primary_span]
pub attr_span: Span,
#[label]

View file

@ -301,9 +301,12 @@ impl<HCX> ToStableHashKey<HCX> for WorkProductId {
self.hash
}
}
unsafe impl StableOrd for WorkProductId {
impl StableOrd for WorkProductId {
// Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well
const CAN_USE_UNSTABLE_SORT: bool = true;
// `WorkProductId` sort order is not affected by (de)serialization.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.

View file

@ -14,7 +14,7 @@ use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, Modul
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError};
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError};
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
use rustc_attr as attr;
@ -1313,7 +1313,17 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
_ => {
let orig_macro_rules_scope = self.parent_scope.macro_rules;
self.build_reduced_graph_for_item(item);
visit::walk_item(self, item);
match item.kind {
ItemKind::Mod(..) => {
// Visit attributes after items for backward compatibility.
// This way they can use `macro_rules` defined later.
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
item.kind.walk(item, AssocCtxt::Trait, self);
visit::walk_list!(self, visit_attribute, &item.attrs);
}
_ => visit::walk_item(self, item),
}
match item.kind {
ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
self.parent_scope.macro_rules
@ -1514,7 +1524,10 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
if krate.is_placeholder {
self.visit_invoc_in_module(krate.id);
} else {
visit::walk_crate(self, krate);
// Visit attributes after items for backward compatibility.
// This way they can use `macro_rules` defined later.
visit::walk_list!(self, visit_item, &krate.items);
visit::walk_list!(self, visit_attribute, &krate.attrs);
self.contains_macro_use(&krate.attrs);
}
}

View file

@ -5,7 +5,7 @@ use crate::errors::CannotDetermineMacroResolution;
use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope};
use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive};
use crate::Namespace::*;
use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, Used};
use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, NameBindingKind, Used};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
use rustc_ast::expand::StrippedCfgItem;
@ -18,15 +18,18 @@ use rustc_errors::{Applicability, StashKey};
use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand};
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::compile_declarative_macro;
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
use rustc_expand::expand::{
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
};
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::middle::stability;
use rustc_middle::ty::RegisteredTools;
use rustc_middle::ty::{TyCtxt, Visibility};
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
use rustc_session::lint::builtin::{
LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, SOFT_UNSTABLE,
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACROS, UNUSED_MACRO_RULES,
};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::edit_distance;
@ -140,9 +143,10 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
}
}
}
// We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools,
// but it's not an error to register them explicitly.
let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri];
// We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known
// tools, but it's not an error to register them explicitly.
let predefined_tools =
[sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri, sym::rust_analyzer];
registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span));
registered_tools
}
@ -288,6 +292,16 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
let parent_scope = &ParentScope { derives, ..parent_scope };
let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
let node_id = invoc.expansion_data.lint_node_id;
// This is a heuristic, but it's good enough for the lint.
let looks_like_invoc_in_mod_inert_attr = self
.invocation_parents
.get(&invoc_id)
.or_else(|| self.invocation_parents.get(&eager_expansion_root))
.map(|&(mod_def_id, _)| mod_def_id)
.filter(|&mod_def_id| {
invoc.fragment_kind == AstFragmentKind::Expr
&& self.tcx.def_kind(mod_def_id) == DefKind::Mod
});
let (ext, res) = self.smart_resolve_macro_path(
path,
kind,
@ -298,6 +312,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
force,
soft_custom_inner_attributes_gate(path, invoc),
deleg_impl,
looks_like_invoc_in_mod_inert_attr,
)?;
let span = invoc.span();
@ -520,6 +535,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
force: bool,
soft_custom_inner_attributes_gate: bool,
deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<LocalDefId>,
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
let (ext, res) = match self.resolve_macro_or_delegation_path(
path,
@ -528,6 +544,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
true,
force,
deleg_impl,
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
) {
Ok((Some(ext), res)) => (ext, res),
Ok((None, res)) => (self.dummy_ext(kind), res),
@ -682,20 +699,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
trace: bool,
force: bool,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None)
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None)
}
fn resolve_macro_or_delegation_path(
&mut self,
path: &ast::Path,
ast_path: &ast::Path,
kind: Option<MacroKind>,
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
let path_span = path.span;
let mut path = Segment::from_path(path);
let path_span = ast_path.span;
let mut path = Segment::from_path(ast_path);
// Possibly apply the macro helper hack
if deleg_impl.is_none()
@ -761,6 +779,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let res = binding.map(|binding| binding.res());
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
self.report_out_of_scope_macro_calls(
ast_path,
parent_scope,
invoc_in_mod_inert_attr,
binding.ok(),
);
res
};
@ -1013,6 +1037,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
fn report_out_of_scope_macro_calls(
&mut self,
path: &ast::Path,
parent_scope: &ParentScope<'a>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
binding: Option<NameBinding<'a>>,
) {
if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr
&& let Some(binding) = binding
// This is a `macro_rules` itself, not some import.
&& let NameBindingKind::Res(res) = binding.kind
&& let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res
// And the `macro_rules` is defined inside the attribute's module,
// so it cannot be in scope unless imported.
&& self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id())
{
// Try to resolve our ident ignoring `macro_rules` scopes.
// If such resolution is successful and gives the same result
// (e.g. if the macro is re-imported), then silence the lint.
let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
let fallback_binding = self.early_resolve_ident_in_lexical_scope(
path.segments[0].ident,
ScopeSet::Macro(MacroKind::Bang),
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
None,
false,
None,
);
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
self.tcx.sess.psess.buffer_lint(
OUT_OF_SCOPE_MACRO_CALLS,
path.span,
node_id,
BuiltinLintDiag::OutOfScopeMacroCalls { path: pprust::path_to_string(path) },
);
}
}
}
pub(crate) fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.

View file

@ -232,7 +232,8 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
.filter(|item| item.kind == ty::AssocKind::Type)
.map(move |assoc_ty| {
super_poly_trait_ref.map_bound(|super_trait_ref| {
let alias_ty = ty::AliasTy::new(tcx, assoc_ty.def_id, super_trait_ref.args);
let alias_ty =
ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args);
let resolved = tcx.normalize_erasing_regions(
ty::ParamEnv::reveal_all(),
alias_ty.to_ty(tcx),
@ -351,7 +352,7 @@ pub fn transform_instance<'tcx>(
// Adjust the type ids of VTableShims to the type id expected in the call sites for the
// entry in the vtable (i.e., by using the signature of the closure passed as an argument
// to the shim, or by just removing self).
let trait_ref = ty::TraitRef::new(tcx, trait_id, instance.args);
let trait_ref = ty::TraitRef::new_from_args(tcx, trait_id, instance.args);
let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
instance.args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
}
@ -432,7 +433,7 @@ pub fn transform_instance<'tcx>(
x => bug!("Unexpected type kind for closure-like: {x:?}"),
};
let concrete_args = tcx.mk_args_trait(closure_ty, inputs.map(Into::into));
let trait_ref = ty::TraitRef::new(tcx, trait_id, concrete_args);
let trait_ref = ty::TraitRef::new_from_args(tcx, trait_id, concrete_args);
let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
let abstract_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
// There should be exactly one method on this trait, and it should be the one we're

View file

@ -498,9 +498,11 @@ pub enum OutputType {
DepInfo,
}
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
unsafe impl StableOrd for OutputType {
impl StableOrd for OutputType {
const CAN_USE_UNSTABLE_SORT: bool = true;
// Trivial C-Style enums have a stable sort order across compilation sessions.
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {

Some files were not shown because too many files have changed in this diff Show more