Auto merge of #139622 - matthiaskrgr:rollup-8ri1vid, r=matthiaskrgr

Rollup of 13 pull requests

Successful merges:

 - #138167 (Small code improvement in rustdoc hidden stripper)
 - #138605 (Clean up librustdoc::html::render to be better encapsulated)
 - #139423 (Suppress missing field error when autoderef bottoms out in infer)
 - #139449 (match ergonomics: replace `peel_off_references` with a recursive call)
 - #139507 (compiletest: Trim whitespace from environment variable names)
 - #139530 (Remove some dead or leftover code related to rustc-intrinsic abi removal)
 - #139560 (fix title of offset_of_enum feature)
 - #139563 (emit a better error message for using the macro incorrectly)
 - #139568 (Don't use empty trait names)
 - #139580 (Temporarily leave the review rotation)
 - #139589 (saethlin is back from vacation)
 - #139592 (rustdoc: Enable Markdown extensions when looking for doctests)
 - #139599 (Tracking issue template: fine-grained information on style update status)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-10 12:18:24 +00:00
commit 69b3959afe
30 changed files with 269 additions and 330 deletions

View File

@ -41,7 +41,10 @@ for larger features an implementation could be broken up into multiple PRs.
- [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring
instructions?)
- [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide])
- [ ] Formatting for new syntax has been added to the [Style Guide] ([nightly-style-procedure])
- [ ] Style updates for any new syntax ([nightly-style-procedure])
- [ ] Style team decision on new formatting
- [ ] Formatting for new syntax has been added to the [Style Guide]
- [ ] (non-blocking) Formatting has been implemented in `rustfmt`
- [ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide])
[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr

View File

@ -234,7 +234,7 @@ mod llvm_enzyme {
let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind {
ast::MetaItemKind::List(ref vec) => vec.clone(),
_ => {
dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() });
return vec![item];
}
};

View File

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
An intrinsic was declared without being a function.
Erroneous code example:
```compile_fail,E0622
```no_run
#![feature(intrinsics)]
#![allow(internal_features)]

View File

@ -397,7 +397,7 @@ E0618: 0618,
E0619: 0619,
E0620: 0620,
E0621: 0621,
E0622: 0622,
E0622: 0622, // REMOVED: rustc-intrinsic ABI was removed
E0623: 0623,
E0624: 0624,
E0625: 0625,

View File

@ -719,7 +719,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
def_id,
tcx.def_ident_span(def_id).unwrap(),
i.name,
ExternAbi::Rust,
)
}
}
@ -787,16 +786,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
for item in items {
let def_id = item.id.owner_id.def_id;
if tcx.has_attr(def_id, sym::rustc_intrinsic) {
intrinsic::check_intrinsic_type(
tcx,
item.id.owner_id.def_id,
item.span,
item.ident.name,
abi,
);
}
let generics = tcx.generics_of(def_id);
let own_counts = generics.own_counts();
if generics.own_params.len() - own_counts.lifetimes != 0 {

View File

@ -1,9 +1,8 @@
//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
use rustc_abi::ExternAbi;
use rustc_errors::codes::*;
use rustc_errors::{DiagMessage, struct_span_code_err};
use rustc_hir::{self as hir, Safety};
use rustc_errors::DiagMessage;
use rustc_hir::{self as hir};
use rustc_middle::bug;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -26,17 +25,10 @@ fn equate_intrinsic_type<'tcx>(
sig: ty::PolyFnSig<'tcx>,
) {
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
| hir::Node::ForeignItem(hir::ForeignItem {
kind: hir::ForeignItemKind::Fn(_, _, generics),
..
}) => (tcx.generics_of(def_id), generics.span),
_ => {
struct_span_code_err!(tcx.dcx(), span, E0622, "intrinsic must be a function")
.with_span_label(span, "expected a function")
.emit();
return;
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
(tcx.generics_of(def_id), generics.span)
}
_ => tcx.dcx().span_bug(span, "intrinsic must be a function"),
};
let own_counts = generics.own_counts();
@ -70,13 +62,7 @@ fn equate_intrinsic_type<'tcx>(
}
/// Returns the unsafety of the given intrinsic.
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
tcx.fn_sig(intrinsic_id).skip_binder().safety()
} else {
// Old-style intrinsics are never safe
Safety::Unsafe
};
fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
// When adding a new intrinsic to this list,
// it's usually worth updating that intrinsic's documentation
@ -148,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
_ => hir::Safety::Unsafe,
};
if has_safe_attr != is_in_list {
if tcx.fn_sig(intrinsic_id).skip_binder().safety() != is_in_list {
tcx.dcx().struct_span_err(
tcx.def_span(intrinsic_id),
DiagMessage::from(format!(
@ -163,12 +149,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(
pub(crate) fn check_intrinsic_type(
tcx: TyCtxt<'_>,
intrinsic_id: LocalDefId,
span: Span,
intrinsic_name: Symbol,
abi: ExternAbi,
) {
let generics = tcx.generics_of(intrinsic_id);
let param = |n| {
@ -706,7 +691,7 @@ pub fn check_intrinsic_type(
};
(n_tps, 0, n_cts, inputs, output, safety)
};
let sig = tcx.mk_fn_sig(inputs, output, false, safety, abi);
let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust);
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
}

View File

@ -2920,8 +2920,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// We failed to check the expression, report an error.
// Emits an error if we deref an infer variable, like calling `.field` on a base type of &_.
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
// Emits an error if we deref an infer variable, like calling `.field` on a base type
// of `&_`. We can also use this to suppress unnecessary "missing field" errors that
// will follow ambiguity errors.
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
if let ty::Error(_) = final_ty.kind() {
return final_ty;
}
if let Some((adjustments, did)) = private_candidate {
// (#90483) apply adjustments to avoid ExprUseVisitor from

View File

@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
enum AdjustMode {
/// Peel off all immediate reference types.
Peel,
/// Reset binding mode to the initial mode.
/// Used for destructuring assignment, where we don't want any match ergonomics.
Reset,
/// Pass on the input binding mode and expected type.
Pass,
}
@ -321,77 +318,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Conversely, inside this module, `check_pat_top` should never be used.
#[instrument(level = "debug", skip(self, pat_info))]
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
let path_res = match pat.kind {
let opt_path_res = match pat.kind {
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
}
_ => None,
};
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
let (expected, binding_mode, max_ref_mutbl) =
self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl);
let pat_info = PatInfo {
binding_mode,
max_ref_mutbl,
top_info: ti,
decl_origin: pat_info.decl_origin,
current_depth: current_depth + 1,
};
let ty = match pat.kind {
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected,
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
let ty = self.check_pat_path(
*hir_id,
pat.hir_id,
*span,
qpath,
path_res.unwrap(),
expected,
&pat_info.top_info,
);
self.write_ty(*hir_id, ty);
ty
}
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
PatKind::Range(lhs, rhs, _) => {
self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
}
PatKind::Binding(ba, var_id, ident, sub) => {
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
}
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
}
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
}
PatKind::Guard(pat, cond) => {
self.check_pat(pat, expected, pat_info);
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
expected
}
PatKind::Or(pats) => {
for pat in pats {
self.check_pat(pat, expected, pat_info);
}
expected
}
PatKind::Tuple(elements, ddpos) => {
self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
}
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
PatKind::Slice(before, slice, after) => {
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
}
};
let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res));
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
self.write_ty(pat.hir_id, ty);
// (note_1): In most of the cases where (note_1) is referenced
@ -437,27 +371,126 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
}
/// Compute the new expected type and default binding mode from the old ones
/// as well as the pattern form we are currently checking.
fn calc_default_binding_mode(
// Helper to avoid resolving the same path pattern several times.
fn check_pat_inner(
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
def_br: ByRef,
opt_path_res: Option<(Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>])>,
adjust_mode: AdjustMode,
max_ref_mutbl: MutblCap,
) -> (Ty<'tcx>, ByRef, MutblCap) {
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
) -> Ty<'tcx> {
#[cfg(debug_assertions)]
if def_br == ByRef::Yes(Mutability::Mut)
&& max_ref_mutbl != MutblCap::Mut
if pat_info.binding_mode == ByRef::Yes(Mutability::Mut)
&& pat_info.max_ref_mutbl != MutblCap::Mut
&& self.downgrade_mut_inside_shared()
{
span_bug!(pat.span, "Pattern mutability cap violated!");
}
match adjust_mode {
AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
// Resolve type if needed.
let expected = if let AdjustMode::Peel = adjust_mode
&& pat.default_binding_modes
{
self.try_structurally_resolve_type(pat.span, expected)
} else {
expected
};
let old_pat_info = pat_info;
let pat_info = PatInfo { current_depth: old_pat_info.current_depth + 1, ..old_pat_info };
match pat.kind {
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
_ if let AdjustMode::Peel = adjust_mode
&& pat.default_binding_modes
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() =>
{
debug!("inspecting {:?}", expected);
debug!("current discriminant is Ref, inserting implicit deref");
// Preserve the reference type. We'll need it later during THIR lowering.
self.typeck_results
.borrow_mut()
.pat_adjustments_mut()
.entry(pat.hir_id)
.or_default()
.push(expected);
let mut binding_mode = ByRef::Yes(match pat_info.binding_mode {
// If default binding mode is by value, make it `ref` or `ref mut`
// (depending on whether we observe `&` or `&mut`).
ByRef::No |
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
ByRef::Yes(Mutability::Mut) => inner_mutability,
// Once a `ref`, always a `ref`.
// This is because a `& &mut` cannot mutate the underlying value.
ByRef::Yes(Mutability::Not) => Mutability::Not,
});
let mut max_ref_mutbl = pat_info.max_ref_mutbl;
if self.downgrade_mut_inside_shared() {
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
}
if binding_mode == ByRef::Yes(Mutability::Not) {
max_ref_mutbl = MutblCap::Not;
}
debug!("default binding mode is now {:?}", binding_mode);
// Use the old pat info to keep `current_depth` to its old value.
let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info };
// Recurse with the new expected type.
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
}
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected,
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
let ty = self.check_pat_path(
*hir_id,
pat.hir_id,
*span,
qpath,
opt_path_res.unwrap(),
expected,
&pat_info.top_info,
);
self.write_ty(*hir_id, ty);
ty
}
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
PatKind::Range(lhs, rhs, _) => {
self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
}
PatKind::Binding(ba, var_id, ident, sub) => {
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
}
PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
}
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
}
PatKind::Guard(pat, cond) => {
self.check_pat(pat, expected, pat_info);
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
expected
}
PatKind::Or(pats) => {
for pat in pats {
self.check_pat(pat, expected, pat_info);
}
expected
}
PatKind::Tuple(elements, ddpos) => {
self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info)
}
PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info),
PatKind::Deref(inner) => self.check_pat_deref(pat.span, inner, expected, pat_info),
PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info),
PatKind::Slice(before, slice, after) => {
self.check_pat_slice(pat.span, before, slice, after, expected, pat_info)
}
}
}
@ -465,11 +498,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
// When we perform destructuring assignment, we disable default match bindings, which are
// unintuitive in this context.
if !pat.default_binding_modes {
return AdjustMode::Reset;
}
match &pat.kind {
// Type checking these product-like types successfully always require
// that the expected type be of those types and not reference types.
@ -526,64 +554,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
/// Peel off as many immediately nested `& mut?` from the expected type as possible
/// and return the new expected type and binding default binding mode.
/// The adjustments vector, if non-empty is stored in a table.
fn peel_off_references(
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
mut def_br: ByRef,
mut max_ref_mutbl: MutblCap,
) -> (Ty<'tcx>, ByRef, MutblCap) {
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
// the `Some(5)` which is not of type Ref.
//
// For each ampersand peeled off, update the binding mode and push the original
// type into the adjustments vector.
//
// See the examples in `ui/match-defbm*.rs`.
let mut pat_adjustments = vec![];
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
debug!("inspecting {:?}", expected);
debug!("current discriminant is Ref, inserting implicit deref");
// Preserve the reference type. We'll need it later during THIR lowering.
pat_adjustments.push(expected);
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
def_br = ByRef::Yes(match def_br {
// If default binding mode is by value, make it `ref` or `ref mut`
// (depending on whether we observe `&` or `&mut`).
ByRef::No |
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
ByRef::Yes(Mutability::Mut) => inner_mutability,
// Once a `ref`, always a `ref`.
// This is because a `& &mut` cannot mutate the underlying value.
ByRef::Yes(Mutability::Not) => Mutability::Not,
});
}
if self.downgrade_mut_inside_shared() {
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
}
if def_br == ByRef::Yes(Mutability::Not) {
max_ref_mutbl = MutblCap::Not;
}
if !pat_adjustments.is_empty() {
debug!("default binding mode is now {:?}", def_br);
self.typeck_results
.borrow_mut()
.pat_adjustments_mut()
.insert(pat.hir_id, pat_adjustments);
}
(expected, def_br, max_ref_mutbl)
}
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
let ty = match &lt.kind {
rustc_hir::PatExprKind::Lit { lit, negated } => {

View File

@ -602,21 +602,13 @@ impl<'a> Parser<'a> {
let polarity = self.parse_polarity();
// Parse both types and traits as a type, then reinterpret if necessary.
let err_path = |span| ast::Path::from_ident(Ident::new(kw::Empty, span));
let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
{
let span = self.prev_token.span.between(self.token.span);
self.dcx().emit_err(errors::MissingTraitInTraitImpl {
return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl {
span,
for_span: span.to(self.token.span),
});
P(Ty {
kind: TyKind::Path(None, err_path(span)),
span,
id: DUMMY_NODE_ID,
tokens: None,
})
}));
} else {
self.parse_ty_with_generics_recovery(&generics)?
};
@ -657,6 +649,7 @@ impl<'a> Parser<'a> {
other => {
if let TyKind::ImplTrait(_, bounds) = other
&& let [bound] = bounds.as_slice()
&& let GenericBound::Trait(poly_trait_ref) = bound
{
// Suggest removing extra `impl` keyword:
// `impl<T: Default> impl Default for Wrapper<T>`
@ -666,12 +659,12 @@ impl<'a> Parser<'a> {
extra_impl_kw,
impl_trait_span: ty_first.span,
});
poly_trait_ref.trait_ref.path.clone()
} else {
self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType {
span: ty_first.span,
});
return Err(self.dcx().create_err(
errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
));
}
err_path(ty_first.span)
}
};
let trait_ref = TraitRef { path, ref_id: ty_first.id };

View File

@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) -> Option<LexicalScopeBinding<'ra>> {
assert!(ns == TypeNS || ns == ValueNS);
let orig_ident = ident;
if ident.name == kw::Empty {
return Some(LexicalScopeBinding::Res(Res::Err));
}
let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
// FIXME(jseyfried) improve `Self` hygiene
let empty_span = ident.span.with_ctxt(SyntaxContext::root());

View File

@ -1,4 +1,4 @@
# `offset_of_slice`
# `offset_of_enum`
The tracking issue for this feature is: [#120141]

View File

@ -721,7 +721,7 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
extra_info: Option<&ExtraInfo<'_>>,
include_non_rust: bool,
) {
let mut parser = Parser::new(doc).into_offset_iter();
let mut parser = Parser::new_ext(doc, main_body_opts()).into_offset_iter();
let mut prev_offset = 0;
let mut nb_lines = 0;
let mut register_header = None;

View File

@ -13,6 +13,9 @@
//! is cloned per-thread and contains information about what is currently being
//! rendered.
//!
//! The main entry point to the rendering system is the implementation of
//! `FormatRenderer` on `Context`.
//!
//! In order to speed up rendering (mostly because of markdown rendering), the
//! rendering process has been parallelized. This parallelization is only
//! exposed through the `crate` method on the context, and then also from the
@ -90,7 +93,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display {
/// Specifies whether rendering directly implemented trait items or ones from a certain Deref
/// impl.
#[derive(Copy, Clone, Debug)]
pub(crate) enum AssocItemRender<'a> {
enum AssocItemRender<'a> {
All,
DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
}
@ -98,7 +101,7 @@ pub(crate) enum AssocItemRender<'a> {
/// For different handling of associated items from the Deref target of a type rather than the type
/// itself.
#[derive(Copy, Clone, PartialEq)]
pub(crate) enum RenderMode {
enum RenderMode {
Normal,
ForDeref { mut_: bool },
}
@ -126,7 +129,7 @@ pub(crate) struct IndexItem {
/// A type used for the search index.
#[derive(Debug, Eq, PartialEq)]
pub(crate) struct RenderType {
struct RenderType {
id: Option<RenderTypeId>,
generics: Option<Vec<RenderType>>,
bindings: Option<Vec<(RenderTypeId, Vec<RenderType>)>>,
@ -137,7 +140,7 @@ impl RenderType {
// The contents of the lists are always integers in self-terminating hex
// form, handled by `RenderTypeId::write_to_string`, so no commas are
// needed to separate the items.
pub fn write_to_string(&self, string: &mut String) {
fn write_to_string(&self, string: &mut String) {
fn write_optional_id(id: Option<RenderTypeId>, string: &mut String) {
// 0 is a sentinel, everything else is one-indexed
match id {
@ -177,7 +180,7 @@ impl RenderType {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum RenderTypeId {
enum RenderTypeId {
DefId(DefId),
Primitive(clean::PrimitiveType),
AssociatedType(Symbol),
@ -186,7 +189,7 @@ pub(crate) enum RenderTypeId {
}
impl RenderTypeId {
pub fn write_to_string(&self, string: &mut String) {
fn write_to_string(&self, string: &mut String) {
let id: i32 = match &self {
// 0 is a sentinel, everything else is one-indexed
// concrete type
@ -209,7 +212,7 @@ pub(crate) struct IndexItemFunctionType {
}
impl IndexItemFunctionType {
pub fn write_to_string<'a>(
fn write_to_string<'a>(
&'a self,
string: &mut String,
backref_queue: &mut VecDeque<&'a IndexItemFunctionType>,
@ -309,7 +312,7 @@ impl ItemEntry {
}
impl ItemEntry {
pub(crate) fn print(&self) -> impl fmt::Display {
fn print(&self) -> impl fmt::Display {
fmt::from_fn(move |f| write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name)))
}
}
@ -760,7 +763,7 @@ fn short_item_info(
// Render the list of items inside one of the sections "Trait Implementations",
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
pub(crate) fn render_impls(
fn render_impls(
cx: &Context<'_>,
mut w: impl Write,
impls: &[&Impl],
@ -1201,7 +1204,7 @@ impl<'a> AssocItemLink<'a> {
}
}
pub fn write_section_heading(
fn write_section_heading(
title: &str,
id: &str,
extra_class: Option<&str>,
@ -1226,7 +1229,7 @@ fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display {
write_section_heading(title, id, None, "")
}
pub(crate) fn render_all_impls(
fn render_all_impls(
mut w: impl Write,
cx: &Context<'_>,
containing_item: &clean::Item,
@ -1473,10 +1476,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
}
}
pub(crate) fn notable_traits_button(
ty: &clean::Type,
cx: &Context<'_>,
) -> Option<impl fmt::Display> {
fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt::Display> {
if ty.is_unit() {
// Very common fast path.
return None;
@ -1588,10 +1588,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
(format!("{:#}", ty.print(cx)), out)
}
pub(crate) fn notable_traits_json<'a>(
tys: impl Iterator<Item = &'a clean::Type>,
cx: &Context<'_>,
) -> String {
fn notable_traits_json<'a>(tys: impl Iterator<Item = &'a clean::Type>, cx: &Context<'_>) -> String {
let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect();
mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2));
struct NotableTraitsMap(Vec<(String, String)>);
@ -2171,7 +2168,7 @@ fn render_rightside(
})
}
pub(crate) fn render_impl_summary(
fn render_impl_summary(
cx: &Context<'_>,
i: &Impl,
parent: &clean::Item,

View File

@ -91,19 +91,21 @@ impl DocFolder for Stripper<'_, '_> {
if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
&& let Some(source_did) = source.did
&& let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local())
{
let reexports = reexport_chain(self.tcx, import_def_id, source_did);
// Check if any reexport in the chain has a hidden source
let has_hidden_source = reexports
.iter()
.filter_map(|reexport| reexport.id())
.any(|reexport_did| self.tcx.is_doc_hidden(reexport_did))
|| self.tcx.is_doc_hidden(source_did);
if has_hidden_source {
if self.tcx.is_doc_hidden(source_did) {
return None;
} else if let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) {
let reexports = reexport_chain(self.tcx, import_def_id, source_did);
// Check if any reexport in the chain has a hidden source
let has_hidden_source = reexports
.iter()
.filter_map(|reexport| reexport.id())
.any(|reexport_did| self.tcx.is_doc_hidden(reexport_did));
if has_hidden_source {
return None;
}
}
}

View File

@ -452,7 +452,7 @@ impl TestProps {
ln,
UNSET_EXEC_ENV,
&mut self.unset_exec_env,
|r| r,
|r| r.trim().to_owned(),
);
config.push_name_value_directive(
ln,
@ -464,7 +464,7 @@ impl TestProps {
ln,
UNSET_RUSTC_ENV,
&mut self.unset_rustc_env,
|r| r,
|r| r.trim().to_owned(),
);
config.push_name_value_directive(
ln,
@ -997,16 +997,13 @@ impl Config {
fn parse_env(nv: String) -> (String, String) {
// nv is either FOO or FOO=BAR
let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
match strs.len() {
1 => (strs.pop().unwrap(), String::new()),
2 => {
let end = strs.pop().unwrap();
(strs.pop().unwrap(), end)
}
n => panic!("Expected 1 or 2 strings, not {}", n),
}
// FIXME(Zalathar): The form without `=` seems to be unused; should
// we drop support for it?
let (name, value) = nv.split_once('=').unwrap_or((&nv, ""));
// Trim whitespace from the name, so that `//@ exec-env: FOO=BAR`
// sees the name as `FOO` and not ` FOO`.
let name = name.trim();
(name.to_owned(), value.to_owned())
}
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {

View File

@ -968,16 +968,16 @@ impl<'test> TestCx<'test> {
delete_after_success: bool,
) -> ProcRes {
let prepare_env = |cmd: &mut Command| {
for key in &self.props.unset_exec_env {
cmd.env_remove(key);
}
for (key, val) in &self.props.exec_env {
cmd.env(key, val);
}
for (key, val) in env_extra {
cmd.env(key, val);
}
for key in &self.props.unset_exec_env {
cmd.env_remove(key);
}
};
let proc_res = match &*self.config.target {

View File

@ -0,0 +1,18 @@
//@ check-pass
//@ compile-flags:--test
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
// Regression test for #139064.
/// Example
///
/// Footnote with multiple paragraphs[^multiple]
///
/// [^multiple]:
/// One
///
/// Two
///
/// Three
pub fn add(left: u64, right: u64) -> u64 {
left + right
}

View File

@ -0,0 +1,5 @@
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

View File

@ -63,7 +63,7 @@ fn dummy() {
// Malformed, where args?
#[autodiff]
pub fn f7(x: f64) {
//~^ ERROR autodiff must be applied to function
//~^ ERROR autodiff requires at least a name and mode
unimplemented!()
}
@ -77,7 +77,7 @@ pub fn f8(x: f64) {
// Invalid attribute syntax
#[autodiff = ""]
pub fn f9(x: f64) {
//~^ ERROR autodiff must be applied to function
//~^ ERROR autodiff requires at least a name and mode
unimplemented!()
}

View File

@ -62,7 +62,7 @@ error: autodiff must be applied to function
LL | let add_one_v2 = |x: u32| -> u32 { x + 1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: autodiff must be applied to function
error: autodiff requires at least a name and mode
--> $DIR/autodiff_illegal.rs:65:1
|
LL | / pub fn f7(x: f64) {
@ -80,7 +80,7 @@ LL | | unimplemented!()
LL | | }
| |_^
error: autodiff must be applied to function
error: autodiff requires at least a name and mode
--> $DIR/autodiff_illegal.rs:79:1
|
LL | / pub fn f9(x: f64) {

View File

@ -0,0 +1,23 @@
//@ edition: 2024
//@ revisions: set unset
//@ run-pass
//@ ignore-cross-compile (assume that non-cross targets have working env vars)
//@ rustc-env: MY_RUSTC_ENV = my-rustc-value
//@ exec-env: MY_EXEC_ENV = my-exec-value
//@[unset] unset-rustc-env: MY_RUSTC_ENV
//@[unset] unset-exec-env: MY_EXEC_ENV
// Check that compiletest trims whitespace from environment variable names
// specified in `rustc-env` and `exec-env` directives, so that
// `//@ exec-env: FOO=bar` sees the name as `FOO` and not ` FOO`.
//
// Values are currently not trimmed.
//
// Since this is a compiletest self-test, only run it on non-cross targets,
// to avoid having to worry about weird targets that don't support env vars.
fn main() {
let is_set = cfg!(set);
assert_eq!(option_env!("MY_RUSTC_ENV"), is_set.then_some(" my-rustc-value"));
assert_eq!(std::env::var("MY_EXEC_ENV").ok().as_deref(), is_set.then_some(" my-exec-value"));
}

View File

@ -1,14 +0,0 @@
#![feature(intrinsics)]
extern "C" {
#[rustc_intrinsic]
pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn();
//~^ ERROR intrinsic must be a function [E0622]
}
fn main() {
unsafe {
atomic_singlethreadfence_seqcst();
}
}

View File

@ -1,9 +0,0 @@
error[E0622]: intrinsic must be a function
--> $DIR/E0622.rs:6:5
|
LL | pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0622`.

View File

@ -0,0 +1,4 @@
impl ! {} // OK
default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
//~^ ERROR `default` is not followed by an item

View File

@ -0,0 +1,18 @@
error: `default` is not followed by an item
--> $DIR/impl-parsing-2.rs:3:1
|
LL | default unsafe FAIL
| ^^^^^^^ the `default` qualifier
|
= note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
error: expected item, found keyword `unsafe`
--> $DIR/impl-parsing-2.rs:3:9
|
LL | default unsafe FAIL
| ^^^^^^ expected item
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
error: aborting due to 2 previous errors

View File

@ -2,9 +2,4 @@ impl ! {} // OK
impl ! where u8: Copy {} // OK
impl Trait Type {} //~ ERROR missing `for` in a trait impl
impl Trait .. {} //~ ERROR missing `for` in a trait impl
impl ?Sized for Type {} //~ ERROR expected a trait, found type
impl ?Sized for .. {} //~ ERROR expected a trait, found type
default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
//~^ ERROR `default` is not followed by an item

View File

@ -9,44 +9,11 @@ help: add `for` here
LL | impl Trait for Type {}
| +++
error: missing `for` in a trait impl
--> $DIR/impl-parsing.rs:5:11
|
LL | impl Trait .. {}
| ^
|
help: add `for` here
|
LL | impl Trait for .. {}
| +++
error: expected a trait, found type
--> $DIR/impl-parsing.rs:6:6
--> $DIR/impl-parsing.rs:5:6
|
LL | impl ?Sized for Type {}
| ^^^^^^
error: expected a trait, found type
--> $DIR/impl-parsing.rs:7:6
|
LL | impl ?Sized for .. {}
| ^^^^^^
error: `default` is not followed by an item
--> $DIR/impl-parsing.rs:9:1
|
LL | default unsafe FAIL
| ^^^^^^^ the `default` qualifier
|
= note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
error: expected item, found keyword `unsafe`
--> $DIR/impl-parsing.rs:9:9
|
LL | default unsafe FAIL
| ^^^^^^ expected item
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
error: aborting due to 6 previous errors
error: aborting due to 2 previous errors

View File

@ -58,6 +58,5 @@ fn main() {
let mut buffer = ArrayVec::new();
let x = buffer.last().unwrap().0.clone();
//~^ ERROR type annotations needed
//~| ERROR no field `0` on type `&_`
buffer.reverse();
}

View File

@ -4,13 +4,6 @@ error[E0282]: type annotations needed
LL | let x = buffer.last().unwrap().0.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
error[E0609]: no field `0` on type `&_`
--> $DIR/issue-65611.rs:59:36
|
LL | let x = buffer.last().unwrap().0.clone();
| ^ unknown field
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0609.
For more information about an error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0282`.

View File

@ -1123,8 +1123,8 @@ cc = ["@ZuseZ4"]
warn_non_default_branch.enable = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"fmease",
"jyn514",
"saethlin",
"Noratrieb",
]