Auto merge of #129873 - matthiaskrgr:rollup-bv849ud, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #127474 (doc: Make block of inline Deref methods foldable)
 - #129678 (Deny imports of `rustc_type_ir::inherent` outside of type ir + new trait solver)
 - #129738 (`rustc_mir_transform` cleanups)
 - #129793 (add extra linebreaks so rustdoc can identify the first sentence)
 - #129804 (Fixed some typos in the standard library documentation/comments)
 - #129837 (Actually parse stdout json, instead of using hacky contains logic.)
 - #129842 (Fix LLVM ABI NAME for riscv64imac-unknown-nuttx-elf)
 - #129843 (Mark myself as on vacation for triagebot)
 - #129858 (Replace walk with visit so we dont skip outermost expr kind in def collector)

Failed merges:

 - #129777 (Add `unreachable_pub`, round 4)
 - #129868 (Remove kobzol vacation status)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-09-02 13:41:42 +00:00
commit a4601859ae
34 changed files with 308 additions and 235 deletions

View File

@ -783,6 +783,9 @@ lint_tykind = usage of `ty::TyKind`
lint_tykind_kind = usage of `ty::TyKind::<kind>`
.suggestion = try using `ty::<kind>` directly
lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
.note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
.label = argument has type `{$arg_ty}`
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value

View File

@ -18,7 +18,7 @@ use tracing::debug;
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
TykindKind, UntranslatableDiag,
TykindKind, TypeIrInherentUsage, UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -277,13 +277,39 @@ declare_tool_lint! {
report_in_external_macro: true
}
declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT]);
declare_tool_lint! {
/// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`.
///
/// This module should only be used within the trait solver.
pub rustc::USAGE_OF_TYPE_IR_INHERENT,
Allow,
"usage `rustc_type_ir::inherent` outside of trait system",
report_in_external_macro: true
}
declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]);
impl<'tcx> LateLintPass<'tcx> for TypeIr {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
// Path segments except for the final.
if let Some(seg) =
path.segments.iter().find(|seg| seg.res.opt_def_id().is_some_and(is_mod_inherent))
{
cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
}
// Final path resolutions, like `use rustc_type_ir::inherent`
else if path.res.iter().any(|res| res.opt_def_id().is_some_and(is_mod_inherent)) {
cx.emit_span_lint(
USAGE_OF_TYPE_IR_INHERENT,
path.segments.last().unwrap().ident.span,
TypeIrInherentUsage,
);
}
let (lo, hi, snippet) = match path.segments {
[.., penultimate, segment]
if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>

View File

@ -918,6 +918,11 @@ pub(crate) struct TyQualified {
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_type_ir_inherent_usage)]
#[note]
pub(crate) struct TypeIrInherentUsage;
#[derive(LintDiagnostic)]
#[diag(lint_non_glob_import_type_ir_inherent)]
pub(crate) struct NonGlobImportTypeIrInherent {

View File

@ -86,7 +86,7 @@ fn add_move_for_packed_drop<'tcx>(
let source_info = terminator.source_info;
let ty = place.ty(body, tcx).ty;
let temp = patch.new_temp(ty, terminator.source_info.span);
let temp = patch.new_temp(ty, source_info.span);
let storage_dead_block = patch.new_block(BasicBlockData {
statements: vec![Statement { source_info, kind: StatementKind::StorageDead(temp) }],

View File

@ -37,24 +37,17 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
if context.is_borrow() {
if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
&& self.tcx.is_builtin_derived(impl_def_id)
{
// If we ever reach here it means that the generated derive
// code is somehow doing an unaligned reference, which it
// shouldn't do.
span_bug!(
self.source_info.span,
"builtin derive created an unaligned reference"
);
} else {
self.tcx
.dcx()
.emit_err(errors::UnalignedPackedRef { span: self.source_info.span });
}
if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
&& self.tcx.is_builtin_derived(impl_def_id)
{
// If we ever reach here it means that the generated derive
// code is somehow doing an unaligned reference, which it
// shouldn't do.
span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
} else {
self.tcx.dcx().emit_err(errors::UnalignedPackedRef { span: self.source_info.span });
}
}
}

View File

@ -63,7 +63,9 @@ use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, InstanceKind, Ty, TyCtxt};
use rustc_middle::ty::{
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt,
};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
@ -113,11 +115,18 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
}
}
struct DerefArgVisitor<'tcx> {
struct SelfArgVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
new_base: Place<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
impl<'tcx> SelfArgVisitor<'tcx> {
fn new(tcx: TyCtxt<'tcx>, elem: ProjectionElem<Local, Ty<'tcx>>) -> Self {
Self { tcx, new_base: Place { local: SELF_ARG, projection: tcx.mk_place_elems(&[elem]) } }
}
}
impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -128,53 +137,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if place.local == SELF_ARG {
replace_base(
place,
Place {
local: SELF_ARG,
projection: self.tcx().mk_place_elems(&[ProjectionElem::Deref]),
},
self.tcx,
);
} else {
self.visit_local(&mut place.local, context, location);
for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(local, SELF_ARG);
}
}
}
}
}
struct PinArgVisitor<'tcx> {
ref_coroutine_ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
assert_ne!(*local, SELF_ARG);
}
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
if place.local == SELF_ARG {
replace_base(
place,
Place {
local: SELF_ARG,
projection: self.tcx().mk_place_elems(&[ProjectionElem::Field(
FieldIdx::ZERO,
self.ref_coroutine_ty,
)]),
},
self.tcx,
);
replace_base(place, self.new_base, self.tcx);
} else {
self.visit_local(&mut place.local, context, location);
@ -198,15 +161,6 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
const SELF_ARG: Local = Local::from_u32(1);
/// Coroutine has not been resumed yet.
const UNRESUMED: usize = CoroutineArgs::UNRESUMED;
/// Coroutine has returned / is completed.
const RETURNED: usize = CoroutineArgs::RETURNED;
/// Coroutine has panicked and is poisoned.
const POISONED: usize = CoroutineArgs::POISONED;
/// Number of reserved variants of coroutine state.
const RESERVED_VARIANTS: usize = CoroutineArgs::RESERVED_VARIANTS;
/// A `yield` point in the coroutine.
struct SuspensionPoint<'tcx> {
/// State discriminant used when suspending or resuming at this point.
@ -261,14 +215,10 @@ impl<'tcx> TransformVisitor<'tcx> {
// `gen` continues return `None`
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
let option_def_id = self.tcx.require_lang_item(LangItem::Option, None);
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
option_def_id,
VariantIdx::ZERO,
self.tcx.mk_args(&[self.old_yield_ty.into()]),
None,
None,
)),
make_aggregate_adt(
option_def_id,
VariantIdx::ZERO,
self.tcx.mk_args(&[self.old_yield_ty.into()]),
IndexVec::new(),
)
}
@ -317,64 +267,28 @@ impl<'tcx> TransformVisitor<'tcx> {
is_return: bool,
statements: &mut Vec<Statement<'tcx>>,
) {
const ZERO: VariantIdx = VariantIdx::ZERO;
const ONE: VariantIdx = VariantIdx::from_usize(1);
let rvalue = match self.coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, None);
let args = self.tcx.mk_args(&[self.old_ret_ty.into()]);
if is_return {
// Poll::Ready(val)
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
poll_def_id,
VariantIdx::ZERO,
args,
None,
None,
)),
IndexVec::from_raw(vec![val]),
)
let (variant_idx, operands) = if is_return {
(ZERO, IndexVec::from_raw(vec![val])) // Poll::Ready(val)
} else {
// Poll::Pending
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
poll_def_id,
VariantIdx::from_usize(1),
args,
None,
None,
)),
IndexVec::new(),
)
}
(ONE, IndexVec::new()) // Poll::Pending
};
make_aggregate_adt(poll_def_id, variant_idx, args, operands)
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
let option_def_id = self.tcx.require_lang_item(LangItem::Option, None);
let args = self.tcx.mk_args(&[self.old_yield_ty.into()]);
if is_return {
// None
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
option_def_id,
VariantIdx::ZERO,
args,
None,
None,
)),
IndexVec::new(),
)
let (variant_idx, operands) = if is_return {
(ZERO, IndexVec::new()) // None
} else {
// Some(val)
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
option_def_id,
VariantIdx::from_usize(1),
args,
None,
None,
)),
IndexVec::from_raw(vec![val]),
)
}
(ONE, IndexVec::from_raw(vec![val])) // Some(val)
};
make_aggregate_adt(option_def_id, variant_idx, args, operands)
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => {
if is_return {
@ -400,31 +314,17 @@ impl<'tcx> TransformVisitor<'tcx> {
let coroutine_state_def_id =
self.tcx.require_lang_item(LangItem::CoroutineState, None);
let args = self.tcx.mk_args(&[self.old_yield_ty.into(), self.old_ret_ty.into()]);
if is_return {
// CoroutineState::Complete(val)
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
coroutine_state_def_id,
VariantIdx::from_usize(1),
args,
None,
None,
)),
IndexVec::from_raw(vec![val]),
)
let variant_idx = if is_return {
ONE // CoroutineState::Complete(val)
} else {
// CoroutineState::Yielded(val)
Rvalue::Aggregate(
Box::new(AggregateKind::Adt(
coroutine_state_def_id,
VariantIdx::ZERO,
args,
None,
None,
)),
IndexVec::from_raw(vec![val]),
)
}
ZERO // CoroutineState::Yielded(val)
};
make_aggregate_adt(
coroutine_state_def_id,
variant_idx,
args,
IndexVec::from_raw(vec![val]),
)
}
};
@ -517,7 +417,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
self.make_state(v, source_info, is_return, &mut data.statements);
let state = if let Some((resume, mut resume_arg)) = resume {
// Yield
let state = RESERVED_VARIANTS + self.suspension_points.len();
let state = CoroutineArgs::RESERVED_VARIANTS + self.suspension_points.len();
// The resume arg target location might itself be remapped if its base local is
// live across a yield.
@ -550,7 +450,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
VariantIdx::new(state)
} else {
// Return
VariantIdx::new(RETURNED) // state for returned
VariantIdx::new(CoroutineArgs::RETURNED) // state for returned
};
data.statements.push(self.set_discr(state, source_info));
data.terminator_mut().kind = TerminatorKind::Return;
@ -560,6 +460,15 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
}
}
fn make_aggregate_adt<'tcx>(
def_id: DefId,
variant_idx: VariantIdx,
args: GenericArgsRef<'tcx>,
operands: IndexVec<FieldIdx, Operand<'tcx>>,
) -> Rvalue<'tcx> {
Rvalue::Aggregate(Box::new(AggregateKind::Adt(def_id, variant_idx, args, None, None)), operands)
}
fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let coroutine_ty = body.local_decls.raw[1].ty;
@ -569,7 +478,7 @@ fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo
body.local_decls.raw[1].ty = ref_coroutine_ty;
// Add a deref to accesses of the coroutine state
DerefArgVisitor { tcx }.visit_body(body);
SelfArgVisitor::new(tcx, ProjectionElem::Deref).visit_body(body);
}
fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@ -584,7 +493,8 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
body.local_decls.raw[1].ty = pin_ref_coroutine_ty;
// Add the Pin field access to accesses of the coroutine state
PinArgVisitor { ref_coroutine_ty, tcx }.visit_body(body);
SelfArgVisitor::new(tcx, ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty))
.visit_body(body);
}
/// Allocates a new local and replaces all references of `local` with it. Returns the new local.
@ -651,8 +561,6 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let local = eliminate_get_context_call(&mut body[bb]);
replace_resume_ty_local(tcx, body, local, context_mut_ref);
}
} else {
continue;
}
}
TerminatorKind::Yield { resume_arg, .. } => {
@ -665,24 +573,23 @@ 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 { 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);
let assign = Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((destination, arg))),
};
bb_data.statements.push(assign);
bb_data.terminator = Some(Terminator {
source_info: terminator.source_info,
kind: TerminatorKind::Goto { target: target.unwrap() },
});
local
} else {
let TerminatorKind::Call { args, destination, target, .. } = terminator.kind else {
bug!();
}
};
let [arg] = *Box::try_from(args).unwrap();
let local = arg.node.place().unwrap().local;
let arg = Rvalue::Use(arg.node);
let assign = Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((destination, arg))),
};
bb_data.statements.push(assign);
bb_data.terminator = Some(Terminator {
source_info: terminator.source_info,
kind: TerminatorKind::Goto { target: target.unwrap() },
});
local
}
#[cfg_attr(not(debug_assertions), allow(unused))]
@ -1085,10 +992,11 @@ fn compute_layout<'tcx>(
// Build the coroutine variant field list.
// Create a map from local indices to coroutine struct indices.
let mut variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
iter::repeat(IndexVec::new()).take(RESERVED_VARIANTS).collect();
iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect();
let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size());
for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() {
let variant_index = VariantIdx::from(RESERVED_VARIANTS + suspension_point_idx);
let variant_index =
VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx);
let mut fields = IndexVec::new();
for (idx, saved_local) in live_locals.iter().enumerate() {
fields.push(saved_local);
@ -1183,12 +1091,10 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
source_info,
kind: TerminatorKind::Drop { place, target, unwind, replace: _ },
} => {
if let Some(local) = place.as_local() {
if local == SELF_ARG {
(target, unwind, source_info)
} else {
continue;
}
if let Some(local) = place.as_local()
&& local == SELF_ARG
{
(target, unwind, source_info)
} else {
continue;
}
@ -1237,7 +1143,7 @@ fn create_coroutine_drop_shim<'tcx>(
let mut cases = create_cases(&mut body, transform, Operation::Drop);
cases.insert(0, (UNRESUMED, drop_clean));
cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean));
// The returned state and the poisoned state fall through to the default
// case which is just to return
@ -1387,7 +1293,9 @@ fn create_coroutine_resume_function<'tcx>(
if can_unwind {
let source_info = SourceInfo::outermost(body.span);
let poison_block = body.basic_blocks_mut().push(BasicBlockData {
statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
statements: vec![
transform.set_discr(VariantIdx::new(CoroutineArgs::POISONED), source_info),
],
terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }),
is_cleanup: true,
});
@ -1419,13 +1327,16 @@ fn create_coroutine_resume_function<'tcx>(
use rustc_middle::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn};
// Jump to the entry point on the unresumed
cases.insert(0, (UNRESUMED, START_BLOCK));
cases.insert(0, (CoroutineArgs::UNRESUMED, START_BLOCK));
// Panic when resumed on the returned or poisoned state
if can_unwind {
cases.insert(
1,
(POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(transform.coroutine_kind))),
(
CoroutineArgs::POISONED,
insert_panic_block(tcx, body, ResumedAfterPanic(transform.coroutine_kind)),
),
);
}
@ -1440,7 +1351,7 @@ fn create_coroutine_resume_function<'tcx>(
transform.insert_none_ret_block(body)
}
};
cases.insert(1, (RETURNED, block));
cases.insert(1, (CoroutineArgs::RETURNED, block));
}
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);

View File

@ -3,13 +3,11 @@
#![feature(box_patterns)]
#![feature(const_type_name)]
#![feature(cow_is_borrowed)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)]
#![feature(let_chains)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(option_get_or_insert_default)]
#![feature(round_char_boundary)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
@ -17,6 +15,7 @@
use hir::ConstContext;
use required_consts::RequiredConstsVisitor;
use rustc_const_eval::check_consts::{self, ConstCx};
use rustc_const_eval::util;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::steal::Steal;
@ -33,6 +32,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_middle::util::Providers;
use rustc_middle::{bug, query, span_bug};
use rustc_mir_dataflow::rustc_peek;
use rustc_span::source_map::Spanned;
use rustc_span::{sym, DUMMY_SP};
use rustc_trait_selection::traits;
@ -108,9 +108,6 @@ mod unreachable_enum_branching;
mod unreachable_prop;
mod validate;
use rustc_const_eval::check_consts::{self, ConstCx};
use rustc_mir_dataflow::rustc_peek;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
pub fn provide(providers: &mut Providers) {
@ -128,7 +125,7 @@ pub fn provide(providers: &mut Providers) {
mir_coroutine_witnesses: coroutine::mir_coroutine_witnesses,
optimized_mir,
is_mir_available,
is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
is_ctfe_mir_available: is_mir_available,
mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable,
mir_inliner_callees: inline::cycle::mir_inliner_callees,
promoted_mir,
@ -221,10 +218,8 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
/// Finds the full set of `DefId`s within the current crate that have
/// MIR associated with them.
fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
let mut set = FxIndexSet::default();
// All body-owners have MIR associated with them.
set.extend(tcx.hir().body_owners());
let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect();
// Additionally, tuple struct/variant constructors have MIR, but
// they don't have a BodyId, so we need to build them separately.
@ -249,8 +244,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
// No need to const-check a non-const `fn`.
match const_kind {
Some(ConstContext::Const { .. } | ConstContext::Static(_))
| Some(ConstContext::ConstFn) => {}
Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {}
None => span_bug!(
tcx.def_span(def),
"`mir_const_qualif` should only be called on const fns and const items"

View File

@ -5,6 +5,7 @@
//! So if you got to this crate from the old solver, it's totally normal.
// tidy-alphabetical-start
#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))]
#![warn(unreachable_pub)]
// tidy-alphabetical-end

View File

@ -223,7 +223,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
// we must create two defs.
let coroutine_def =
self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span);
self.with_parent(coroutine_def, |this| visit::walk_expr(this, body));
self.with_parent(coroutine_def, |this| this.visit_expr(body));
}
_ => visit::walk_fn(self, fn_kind),
}

View File

@ -21,7 +21,6 @@ pub fn target() -> Target {
os: "nuttx".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
features: "+m,+a,+c".into(),

View File

@ -5,6 +5,7 @@
feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
)]
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))]
// tidy-alphabetical-end
extern crate self as rustc_type_ir;

View File

@ -3302,7 +3302,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> {
Some(kv)
}
/// Removes the precending element from the `BTreeMap`.
/// Removes the preceding element from the `BTreeMap`.
///
/// The element that was removed is returned. The cursor position is
/// unchanged (after the removed element).
@ -3408,7 +3408,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> {
self.inner.remove_next()
}
/// Removes the precending element from the `BTreeMap`.
/// Removes the preceding element from the `BTreeMap`.
///
/// The element that was removed is returned. The cursor position is
/// unchanged (after the removed element).

View File

@ -2298,7 +2298,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> {
self.inner.remove_next().map(|(k, _)| k)
}
/// Removes the precending element from the `BTreeSet`.
/// Removes the preceding element from the `BTreeSet`.
///
/// The element that was removed is returned. The cursor position is
/// unchanged (after the removed element).
@ -2384,7 +2384,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> {
self.inner.remove_next().map(|(k, _)| k)
}
/// Removes the precending element from the `BTreeSet`.
/// Removes the preceding element from the `BTreeSet`.
///
/// The element that was removed is returned. The cursor position is
/// unchanged (after the removed element).

View File

@ -37,7 +37,7 @@ pub use iter::IntoIter;
///
/// # Example
///
/// Creating muliple copies of a `String`:
/// Creating multiple copies of a `String`:
/// ```rust
/// #![feature(array_repeat)]
///

View File

@ -157,7 +157,7 @@ async unsafe fn surface_drop_in_place<T: Drop + ?Sized>(ptr: *mut T) {
unsafe { crate::ops::fallback_surface_drop(&mut *ptr) }
}
/// Wraps a future to continue outputing `Poll::Ready(())` once after
/// Wraps a future to continue outputting `Poll::Ready(())` once after
/// wrapped future completes by returning `Poll::Ready(())` on poll. This
/// is useful for constructing async destructors to guarantee this
/// "fuse" property
@ -223,7 +223,7 @@ where
/// # Safety
///
/// Same as `async_drop_in_place` except is lazy to avoid creating
/// multiple mutable refernces.
/// multiple mutable references.
#[lang = "async_drop_defer"]
async unsafe fn defer<T: ?Sized>(to_drop: *mut T) {
// SAFETY: same safety requirements as `async_drop_in_place`

View File

@ -1,6 +1,7 @@
#![stable(feature = "core_hint", since = "1.27.0")]
//! Hints to compiler that affects how code should be emitted or optimized.
//!
//! Hints may be compile time or runtime.
use crate::{intrinsics, ub_checks};

View File

@ -310,7 +310,7 @@ define!(
);
define!(
"mir_unwind_cleanup",
/// An unwind action that continues execution in a given basic blok.
/// An unwind action that continues execution in a given basic block.
fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg
);

View File

@ -1072,7 +1072,7 @@ pub(crate) mod builtin {
/// If the environment variable is not defined, then a compilation error
/// will be emitted. To not emit a compile error, use the [`option_env!`]
/// macro instead. A compilation error will also be emitted if the
/// environment variable is not a vaild Unicode string.
/// environment variable is not a valid Unicode string.
///
/// # Examples
///

View File

@ -832,8 +832,9 @@ mod prim_array {}
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here
/// means that elements are laid out so that every element is the same
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// Contiguous here means that elements are laid out so that every element is the same
/// distance from its neighbors.
///
/// *[See also the `std::slice` module](crate::slice).*

View File

@ -142,7 +142,7 @@ fn main() {
// Configure platforms that have reliable basics but may have unreliable math.
// LLVM is currenlty adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
// LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
let has_reliable_f16_math = has_reliable_f16
&& match (target_arch.as_str(), target_os.as_str()) {
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.

View File

@ -738,7 +738,7 @@ fn read_buf_full_read() {
#[test]
// Miri does not support signalling OOM
#[cfg_attr(miri, ignore)]
// 64-bit only to be sure the allocator will fail fast on an impossible to satsify size
// 64-bit only to be sure the allocator will fail fast on an impossible to satisfy size
#[cfg(target_pointer_width = "64")]
fn try_oom_error() {
let mut v = Vec::<u8>::new();

View File

@ -146,7 +146,7 @@ fn lang_start_internal(
rtabort!("drop of the panic payload panicked");
});
panic::catch_unwind(cleanup).map_err(rt_abort)?;
// Guard against multple threads calling `libc::exit` concurrently.
// Guard against multiple threads calling `libc::exit` concurrently.
// See the documentation for `unique_thread_exit` for more information.
panic::catch_unwind(|| crate::sys::exit_guard::unique_thread_exit()).map_err(rt_abort)?;
ret_code

View File

@ -551,7 +551,7 @@ impl<T> Channel<T> {
let mut head = self.head.index.load(Ordering::Acquire);
// The channel may be uninitialized, so we have to swap to avoid overwriting any sender's attempts
// to initalize the first block before noticing that the receivers disconnected. Late allocations
// to initialize the first block before noticing that the receivers disconnected. Late allocations
// will be deallocated by the sender in Drop.
let mut block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);

View File

@ -470,7 +470,7 @@ mod uefi_command_internal {
let st_size = unsafe { (*self.st.as_ptr()).hdr.header_size as usize };
let mut crc32: u32 = 0;
// Set crc to 0 before calcuation
// Set crc to 0 before calculation
unsafe {
(*self.st.as_mut_ptr()).hdr.crc32 = 0;
}

View File

@ -215,7 +215,7 @@ impl Socket {
_ => {
if cfg!(target_os = "vxworks") {
// VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the
// connnection actually succeeded and return ok only when the socket is
// connection actually succeeded and return ok only when the socket is
// ready and no errors were found.
if let Some(e) = self.take_error()? {
return Err(e);

View File

@ -1250,6 +1250,7 @@ fn render_assoc_items_inner(
let Some(v) = cache.impls.get(&it) else { return };
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
let mut close_tags = <Vec<&str>>::with_capacity(1);
let mut tmp_buf = Buffer::html();
let (render_mode, id, class_html) = match what {
AssocItemRender::All => {
@ -1260,6 +1261,8 @@ fn render_assoc_items_inner(
let id =
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
let derived_id = cx.derive_id(&id);
tmp_buf.write_str("<details class=\"toggle big-toggle\" open><summary>");
close_tags.push("</details>");
write_impl_section_heading(
&mut tmp_buf,
&format!(
@ -1269,6 +1272,7 @@ fn render_assoc_items_inner(
),
&id,
);
tmp_buf.write_str("</summary>");
if let Some(def_id) = type_.def_id(cx.cache()) {
cx.deref_id_map.insert(def_id, id);
}
@ -1302,6 +1306,9 @@ fn render_assoc_items_inner(
impls_buf.into_inner()
)
.unwrap();
for tag in close_tags.into_iter().rev() {
w.write_str(tag).unwrap();
}
}
}
@ -1558,7 +1565,7 @@ fn render_impl(
let cache = &shared.cache;
let traits = &cache.traits;
let trait_ = i.trait_did().map(|did| &traits[&did]);
let mut close_tags = String::new();
let mut close_tags = <Vec<&str>>::with_capacity(2);
// For trait implementations, the `interesting` output contains all methods that have doc
// comments, and the `boring` output contains all methods that do not. The distinction is
@ -1870,7 +1877,7 @@ fn render_impl(
if render_mode == RenderMode::Normal {
let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
if toggled {
close_tags.insert_str(0, "</details>");
close_tags.push("</details>");
write!(
w,
"<details class=\"toggle implementors-toggle\"{}>\
@ -1916,14 +1923,16 @@ fn render_impl(
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
close_tags.insert_str(0, "</div>");
close_tags.push("</div>");
}
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.push_buffer(default_impl_items);
w.push_buffer(impl_items);
}
w.write_str(&close_tags);
for tag in close_tags.into_iter().rev() {
w.write_str(tag);
}
}
// Render the items that appear on the right side of methods, impls, and

View File

@ -1852,6 +1852,11 @@ details.toggle {
position: relative;
}
details.big-toggle {
/* This makes [-] on the same line as <summary>. */
contain: inline-size;
}
/* The hideme class is used on summary tags that contain a span with
placeholder text shown only when the toggle is closed. For instance,
"Expand description" or "Show methods". */
@ -1942,6 +1947,11 @@ details.toggle > summary:not(.hideme)::before {
left: -24px;
}
details.big-toggle > summary:not(.hideme)::before {
left: -34px;
top: 9px;
}
/* When a "hideme" summary is open and the "Expand description" or "Show
methods" text is hidden, we want the [-] toggle that remains to not
affect the layout of the items to its right. To do that, we use

View File

@ -4,17 +4,28 @@
use std::path::PathBuf;
use run_make_support::path_helpers::{cwd, has_extension, read_dir_entries_recursive};
use run_make_support::rustdoc;
use run_make_support::{rustdoc, serde_json};
fn main() {
// First we check that we generate the JSON in the stdout.
rustdoc()
let json_string = rustdoc()
.input("foo.rs")
.out_dir("-")
.arg("-Zunstable-options")
.output_format("json")
.run()
.assert_stdout_contains("{\"");
.stdout_utf8();
// First we check that we generate the JSON in the stdout.
let json_value: serde_json::Value =
serde_json::from_str(&json_string).expect("stdout should be valid json");
// We don't care to test the specifics of the JSON, as that's done
// elsewhere, just check that it has a format_version (as all JSON output
// should).
let format_version = json_value["format_version"]
.as_i64()
.expect("json output should contain format_version field");
assert!(format_version > 30);
// Then we check it didn't generate any JSON file.
read_dir_entries_recursive(cwd(), |path| {

View File

@ -0,0 +1,30 @@
// This test ensures that several clickable items actually have the pointer cursor.
go-to: "file://" + |DOC_PATH| + "/lib2/struct.Derefer.html"
assert-text: (".big-toggle summary", "Methods from Deref<Target = str>§")
// We ensure it doesn't go over `§`.
assert-css: (".big-toggle summary::before", {
"left": "-34px",
"top": "9px",
})
// It should NOT have the same X or Y position as the other toggles.
compare-elements-position-false: (
".big-toggle summary::before",
".method-toggle summary::before",
["x", "y"],
)
// We now check that if we're in mobile mode, it gets back to its original X position.
set-window-size: (600, 600)
assert-css: (".big-toggle summary::before", {
"left": "-11px",
"top": "9px",
})
// It should have the same X position as the other toggles.
compare-elements-position: (".big-toggle summary::before", ".method-toggle summary::before", ["x"])
// But still shouldn't have the same Y position.
compare-elements-position-false: (
".big-toggle summary::before",
".method-toggle summary::before",
["y"],
)

View File

@ -356,3 +356,13 @@ pub mod scroll_traits {
fn this_is_a_method_with_a_long_name_returning_something() -> String;
}
}
pub struct Derefer(String);
impl std::ops::Deref for Derefer {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}

View File

@ -0,0 +1,18 @@
//@ compile-flags: -Z unstable-options
// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run.
//@ ignore-stage1
#![feature(rustc_private)]
#![deny(rustc::usage_of_type_ir_inherent)]
extern crate rustc_type_ir;
use rustc_type_ir::inherent::*;
//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
use rustc_type_ir::inherent;
//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
use rustc_type_ir::inherent::Predicate;
//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
fn main() {}

View File

@ -0,0 +1,31 @@
error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
--> $DIR/import-of-type-ir-inherent.rs:11:20
|
LL | use rustc_type_ir::inherent::*;
| ^^^^^^^^
|
= note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
note: the lint level is defined here
--> $DIR/import-of-type-ir-inherent.rs:7:9
|
LL | #![deny(rustc::usage_of_type_ir_inherent)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
--> $DIR/import-of-type-ir-inherent.rs:13:20
|
LL | use rustc_type_ir::inherent;
| ^^^^^^^^
|
= note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
--> $DIR/import-of-type-ir-inherent.rs:15:20
|
LL | use rustc_type_ir::inherent::Predicate;
| ^^^^^^^^
|
= note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
error: aborting due to 3 previous errors

View File

@ -0,0 +1,12 @@
//@ edition: 2021
//@ check-pass
#![feature(async_closure)]
// Make sure we don't ICE if an async closure has a macro body.
// This happened because we were calling walk instead of visit
// in the def collector, oops!
fn main() {
let _ = async || println!();
}

View File

@ -913,7 +913,14 @@ cc = ["@kobzol"]
[assign]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "kobzol", "joboet"]
users_on_vacation = [
"jhpratt",
"joboet",
"jyn514",
"kobzol",
"oli-obk",
"tgross35",
]
[assign.adhoc_groups]
compiler-team = [