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:
commit
69b3959afe
30 changed files with 269 additions and 330 deletions
5
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
5
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
|
@ -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
|
- [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring
|
||||||
instructions?)
|
instructions?)
|
||||||
- [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide])
|
- [ ] 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 PR ([see instructions on rustc-dev-guide][stabilization-guide])
|
||||||
|
|
||||||
[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr
|
[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr
|
||||||
|
|
|
@ -234,7 +234,7 @@ mod llvm_enzyme {
|
||||||
let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind {
|
let meta_item_vec: ThinVec<MetaItemInner> = match meta_item.kind {
|
||||||
ast::MetaItemKind::List(ref vec) => vec.clone(),
|
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];
|
return vec![item];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
#### Note: this error code is no longer emitted by the compiler.
|
||||||
|
|
||||||
An intrinsic was declared without being a function.
|
An intrinsic was declared without being a function.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0622
|
```no_run
|
||||||
#![feature(intrinsics)]
|
#![feature(intrinsics)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ E0618: 0618,
|
||||||
E0619: 0619,
|
E0619: 0619,
|
||||||
E0620: 0620,
|
E0620: 0620,
|
||||||
E0621: 0621,
|
E0621: 0621,
|
||||||
E0622: 0622,
|
E0622: 0622, // REMOVED: rustc-intrinsic ABI was removed
|
||||||
E0623: 0623,
|
E0623: 0623,
|
||||||
E0624: 0624,
|
E0624: 0624,
|
||||||
E0625: 0625,
|
E0625: 0625,
|
||||||
|
|
|
@ -719,7 +719,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
def_id,
|
def_id,
|
||||||
tcx.def_ident_span(def_id).unwrap(),
|
tcx.def_ident_span(def_id).unwrap(),
|
||||||
i.name,
|
i.name,
|
||||||
ExternAbi::Rust,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -787,16 +786,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
for item in items {
|
for item in items {
|
||||||
let def_id = item.id.owner_id.def_id;
|
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 generics = tcx.generics_of(def_id);
|
||||||
let own_counts = generics.own_counts();
|
let own_counts = generics.own_counts();
|
||||||
if generics.own_params.len() - own_counts.lifetimes != 0 {
|
if generics.own_params.len() - own_counts.lifetimes != 0 {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
|
//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::DiagMessage;
|
||||||
use rustc_errors::{DiagMessage, struct_span_code_err};
|
use rustc_hir::{self as hir};
|
||||||
use rustc_hir::{self as hir, Safety};
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
@ -26,17 +25,10 @@ fn equate_intrinsic_type<'tcx>(
|
||||||
sig: ty::PolyFnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
) {
|
) {
|
||||||
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
|
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
|
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => {
|
||||||
| hir::Node::ForeignItem(hir::ForeignItem {
|
(tcx.generics_of(def_id), generics.span)
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
_ => tcx.dcx().span_bug(span, "intrinsic must be a function"),
|
||||||
};
|
};
|
||||||
let own_counts = generics.own_counts();
|
let own_counts = generics.own_counts();
|
||||||
|
|
||||||
|
@ -70,13 +62,7 @@ fn equate_intrinsic_type<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the unsafety of the given intrinsic.
|
/// Returns the unsafety of the given intrinsic.
|
||||||
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety {
|
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
|
|
||||||
};
|
|
||||||
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
|
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
|
||||||
// When adding a new intrinsic to this list,
|
// When adding a new intrinsic to this list,
|
||||||
// it's usually worth updating that intrinsic's documentation
|
// 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,
|
_ => 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.dcx().struct_span_err(
|
||||||
tcx.def_span(intrinsic_id),
|
tcx.def_span(intrinsic_id),
|
||||||
DiagMessage::from(format!(
|
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`,
|
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
|
||||||
/// and in `library/core/src/intrinsics.rs`.
|
/// and in `library/core/src/intrinsics.rs`.
|
||||||
pub fn check_intrinsic_type(
|
pub(crate) fn check_intrinsic_type(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
intrinsic_id: LocalDefId,
|
intrinsic_id: LocalDefId,
|
||||||
span: Span,
|
span: Span,
|
||||||
intrinsic_name: Symbol,
|
intrinsic_name: Symbol,
|
||||||
abi: ExternAbi,
|
|
||||||
) {
|
) {
|
||||||
let generics = tcx.generics_of(intrinsic_id);
|
let generics = tcx.generics_of(intrinsic_id);
|
||||||
let param = |n| {
|
let param = |n| {
|
||||||
|
@ -706,7 +691,7 @@ pub fn check_intrinsic_type(
|
||||||
};
|
};
|
||||||
(n_tps, 0, n_cts, inputs, output, safety)
|
(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);
|
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
|
||||||
equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
|
equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2920,8 +2920,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
// We failed to check the expression, report an error.
|
// 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 &_.
|
// Emits an error if we deref an infer variable, like calling `.field` on a base type
|
||||||
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
// 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 {
|
if let Some((adjustments, did)) = private_candidate {
|
||||||
// (#90483) apply adjustments to avoid ExprUseVisitor from
|
// (#90483) apply adjustments to avoid ExprUseVisitor from
|
||||||
|
|
|
@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
enum AdjustMode {
|
enum AdjustMode {
|
||||||
/// Peel off all immediate reference types.
|
/// Peel off all immediate reference types.
|
||||||
Peel,
|
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 on the input binding mode and expected type.
|
||||||
Pass,
|
Pass,
|
||||||
}
|
}
|
||||||
|
@ -321,77 +318,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// Conversely, inside this module, `check_pat_top` should never be used.
|
/// Conversely, inside this module, `check_pat_top` should never be used.
|
||||||
#[instrument(level = "debug", skip(self, pat_info))]
|
#[instrument(level = "debug", skip(self, pat_info))]
|
||||||
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
|
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 opt_path_res = match pat.kind {
|
||||||
|
|
||||||
let path_res = match pat.kind {
|
|
||||||
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
|
||||||
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
|
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
|
let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res));
|
||||||
let (expected, binding_mode, max_ref_mutbl) =
|
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
|
||||||
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)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.write_ty(pat.hir_id, ty);
|
self.write_ty(pat.hir_id, ty);
|
||||||
|
|
||||||
// (note_1): In most of the cases where (note_1) is referenced
|
// (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`,
|
// `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the new expected type and default binding mode from the old ones
|
// Helper to avoid resolving the same path pattern several times.
|
||||||
/// as well as the pattern form we are currently checking.
|
fn check_pat_inner(
|
||||||
fn calc_default_binding_mode(
|
|
||||||
&self,
|
&self,
|
||||||
pat: &'tcx Pat<'tcx>,
|
pat: &'tcx Pat<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
opt_path_res: Option<(Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>])>,
|
||||||
def_br: ByRef,
|
|
||||||
adjust_mode: AdjustMode,
|
adjust_mode: AdjustMode,
|
||||||
max_ref_mutbl: MutblCap,
|
expected: Ty<'tcx>,
|
||||||
) -> (Ty<'tcx>, ByRef, MutblCap) {
|
pat_info: PatInfo<'tcx>,
|
||||||
|
) -> Ty<'tcx> {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
if def_br == ByRef::Yes(Mutability::Mut)
|
if pat_info.binding_mode == ByRef::Yes(Mutability::Mut)
|
||||||
&& max_ref_mutbl != MutblCap::Mut
|
&& pat_info.max_ref_mutbl != MutblCap::Mut
|
||||||
&& self.downgrade_mut_inside_shared()
|
&& self.downgrade_mut_inside_shared()
|
||||||
{
|
{
|
||||||
span_bug!(pat.span, "Pattern mutability cap violated!");
|
span_bug!(pat.span, "Pattern mutability cap violated!");
|
||||||
}
|
}
|
||||||
match adjust_mode {
|
|
||||||
AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
|
// Resolve type if needed.
|
||||||
AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
|
let expected = if let AdjustMode::Peel = adjust_mode
|
||||||
AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
|
&& 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)`.
|
/// 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 {
|
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 {
|
match &pat.kind {
|
||||||
// Type checking these product-like types successfully always require
|
// Type checking these product-like types successfully always require
|
||||||
// that the expected type be of those types and not reference types.
|
// 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> {
|
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
|
||||||
let ty = match <.kind {
|
let ty = match <.kind {
|
||||||
rustc_hir::PatExprKind::Lit { lit, negated } => {
|
rustc_hir::PatExprKind::Lit { lit, negated } => {
|
||||||
|
|
|
@ -602,21 +602,13 @@ impl<'a> Parser<'a> {
|
||||||
let polarity = self.parse_polarity();
|
let polarity = self.parse_polarity();
|
||||||
|
|
||||||
// Parse both types and traits as a type, then reinterpret if necessary.
|
// 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 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);
|
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,
|
span,
|
||||||
for_span: span.to(self.token.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 {
|
} else {
|
||||||
self.parse_ty_with_generics_recovery(&generics)?
|
self.parse_ty_with_generics_recovery(&generics)?
|
||||||
};
|
};
|
||||||
|
@ -657,6 +649,7 @@ impl<'a> Parser<'a> {
|
||||||
other => {
|
other => {
|
||||||
if let TyKind::ImplTrait(_, bounds) = other
|
if let TyKind::ImplTrait(_, bounds) = other
|
||||||
&& let [bound] = bounds.as_slice()
|
&& let [bound] = bounds.as_slice()
|
||||||
|
&& let GenericBound::Trait(poly_trait_ref) = bound
|
||||||
{
|
{
|
||||||
// Suggest removing extra `impl` keyword:
|
// Suggest removing extra `impl` keyword:
|
||||||
// `impl<T: Default> impl Default for Wrapper<T>`
|
// `impl<T: Default> impl Default for Wrapper<T>`
|
||||||
|
@ -666,12 +659,12 @@ impl<'a> Parser<'a> {
|
||||||
extra_impl_kw,
|
extra_impl_kw,
|
||||||
impl_trait_span: ty_first.span,
|
impl_trait_span: ty_first.span,
|
||||||
});
|
});
|
||||||
|
poly_trait_ref.trait_ref.path.clone()
|
||||||
} else {
|
} else {
|
||||||
self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType {
|
return Err(self.dcx().create_err(
|
||||||
span: ty_first.span,
|
errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span },
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
err_path(ty_first.span)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let trait_ref = TraitRef { path, ref_id: ty_first.id };
|
let trait_ref = TraitRef { path, ref_id: ty_first.id };
|
||||||
|
|
|
@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
) -> Option<LexicalScopeBinding<'ra>> {
|
) -> Option<LexicalScopeBinding<'ra>> {
|
||||||
assert!(ns == TypeNS || ns == ValueNS);
|
assert!(ns == TypeNS || ns == ValueNS);
|
||||||
let orig_ident = ident;
|
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 {
|
let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
|
||||||
// FIXME(jseyfried) improve `Self` hygiene
|
// FIXME(jseyfried) improve `Self` hygiene
|
||||||
let empty_span = ident.span.with_ctxt(SyntaxContext::root());
|
let empty_span = ident.span.with_ctxt(SyntaxContext::root());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# `offset_of_slice`
|
# `offset_of_enum`
|
||||||
|
|
||||||
The tracking issue for this feature is: [#120141]
|
The tracking issue for this feature is: [#120141]
|
||||||
|
|
||||||
|
|
|
@ -721,7 +721,7 @@ pub(crate) fn find_codes<T: doctest::DocTestVisitor>(
|
||||||
extra_info: Option<&ExtraInfo<'_>>,
|
extra_info: Option<&ExtraInfo<'_>>,
|
||||||
include_non_rust: bool,
|
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 prev_offset = 0;
|
||||||
let mut nb_lines = 0;
|
let mut nb_lines = 0;
|
||||||
let mut register_header = None;
|
let mut register_header = None;
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
//! is cloned per-thread and contains information about what is currently being
|
//! is cloned per-thread and contains information about what is currently being
|
||||||
//! rendered.
|
//! 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
|
//! In order to speed up rendering (mostly because of markdown rendering), the
|
||||||
//! rendering process has been parallelized. This parallelization is only
|
//! rendering process has been parallelized. This parallelization is only
|
||||||
//! exposed through the `crate` method on the context, and then also from the
|
//! 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
|
/// Specifies whether rendering directly implemented trait items or ones from a certain Deref
|
||||||
/// impl.
|
/// impl.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) enum AssocItemRender<'a> {
|
enum AssocItemRender<'a> {
|
||||||
All,
|
All,
|
||||||
DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
|
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
|
/// For different handling of associated items from the Deref target of a type rather than the type
|
||||||
/// itself.
|
/// itself.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub(crate) enum RenderMode {
|
enum RenderMode {
|
||||||
Normal,
|
Normal,
|
||||||
ForDeref { mut_: bool },
|
ForDeref { mut_: bool },
|
||||||
}
|
}
|
||||||
|
@ -126,7 +129,7 @@ pub(crate) struct IndexItem {
|
||||||
|
|
||||||
/// A type used for the search index.
|
/// A type used for the search index.
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub(crate) struct RenderType {
|
struct RenderType {
|
||||||
id: Option<RenderTypeId>,
|
id: Option<RenderTypeId>,
|
||||||
generics: Option<Vec<RenderType>>,
|
generics: Option<Vec<RenderType>>,
|
||||||
bindings: Option<Vec<(RenderTypeId, 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
|
// The contents of the lists are always integers in self-terminating hex
|
||||||
// form, handled by `RenderTypeId::write_to_string`, so no commas are
|
// form, handled by `RenderTypeId::write_to_string`, so no commas are
|
||||||
// needed to separate the items.
|
// 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) {
|
fn write_optional_id(id: Option<RenderTypeId>, string: &mut String) {
|
||||||
// 0 is a sentinel, everything else is one-indexed
|
// 0 is a sentinel, everything else is one-indexed
|
||||||
match id {
|
match id {
|
||||||
|
@ -177,7 +180,7 @@ impl RenderType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub(crate) enum RenderTypeId {
|
enum RenderTypeId {
|
||||||
DefId(DefId),
|
DefId(DefId),
|
||||||
Primitive(clean::PrimitiveType),
|
Primitive(clean::PrimitiveType),
|
||||||
AssociatedType(Symbol),
|
AssociatedType(Symbol),
|
||||||
|
@ -186,7 +189,7 @@ pub(crate) enum RenderTypeId {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
let id: i32 = match &self {
|
||||||
// 0 is a sentinel, everything else is one-indexed
|
// 0 is a sentinel, everything else is one-indexed
|
||||||
// concrete type
|
// concrete type
|
||||||
|
@ -209,7 +212,7 @@ pub(crate) struct IndexItemFunctionType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexItemFunctionType {
|
impl IndexItemFunctionType {
|
||||||
pub fn write_to_string<'a>(
|
fn write_to_string<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
string: &mut String,
|
string: &mut String,
|
||||||
backref_queue: &mut VecDeque<&'a IndexItemFunctionType>,
|
backref_queue: &mut VecDeque<&'a IndexItemFunctionType>,
|
||||||
|
@ -309,7 +312,7 @@ impl ItemEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
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)))
|
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",
|
// Render the list of items inside one of the sections "Trait Implementations",
|
||||||
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
|
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
|
||||||
pub(crate) fn render_impls(
|
fn render_impls(
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
mut w: impl Write,
|
mut w: impl Write,
|
||||||
impls: &[&Impl],
|
impls: &[&Impl],
|
||||||
|
@ -1201,7 +1204,7 @@ impl<'a> AssocItemLink<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_section_heading(
|
fn write_section_heading(
|
||||||
title: &str,
|
title: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
extra_class: Option<&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, "")
|
write_section_heading(title, id, None, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn render_all_impls(
|
fn render_all_impls(
|
||||||
mut w: impl Write,
|
mut w: impl Write,
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
containing_item: &clean::Item,
|
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(
|
fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt::Display> {
|
||||||
ty: &clean::Type,
|
|
||||||
cx: &Context<'_>,
|
|
||||||
) -> Option<impl fmt::Display> {
|
|
||||||
if ty.is_unit() {
|
if ty.is_unit() {
|
||||||
// Very common fast path.
|
// Very common fast path.
|
||||||
return None;
|
return None;
|
||||||
|
@ -1588,10 +1588,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
|
||||||
(format!("{:#}", ty.print(cx)), out)
|
(format!("{:#}", ty.print(cx)), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn notable_traits_json<'a>(
|
fn notable_traits_json<'a>(tys: impl Iterator<Item = &'a clean::Type>, cx: &Context<'_>) -> String {
|
||||||
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();
|
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));
|
mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2));
|
||||||
struct NotableTraitsMap(Vec<(String, String)>);
|
struct NotableTraitsMap(Vec<(String, String)>);
|
||||||
|
@ -2171,7 +2168,7 @@ fn render_rightside(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn render_impl_summary(
|
fn render_impl_summary(
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
i: &Impl,
|
i: &Impl,
|
||||||
parent: &clean::Item,
|
parent: &clean::Item,
|
||||||
|
|
|
@ -91,19 +91,21 @@ impl DocFolder for Stripper<'_, '_> {
|
||||||
|
|
||||||
if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
|
if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
|
||||||
&& let Some(source_did) = source.did
|
&& 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);
|
if self.tcx.is_doc_hidden(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 {
|
|
||||||
return None;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -452,7 +452,7 @@ impl TestProps {
|
||||||
ln,
|
ln,
|
||||||
UNSET_EXEC_ENV,
|
UNSET_EXEC_ENV,
|
||||||
&mut self.unset_exec_env,
|
&mut self.unset_exec_env,
|
||||||
|r| r,
|
|r| r.trim().to_owned(),
|
||||||
);
|
);
|
||||||
config.push_name_value_directive(
|
config.push_name_value_directive(
|
||||||
ln,
|
ln,
|
||||||
|
@ -464,7 +464,7 @@ impl TestProps {
|
||||||
ln,
|
ln,
|
||||||
UNSET_RUSTC_ENV,
|
UNSET_RUSTC_ENV,
|
||||||
&mut self.unset_rustc_env,
|
&mut self.unset_rustc_env,
|
||||||
|r| r,
|
|r| r.trim().to_owned(),
|
||||||
);
|
);
|
||||||
config.push_name_value_directive(
|
config.push_name_value_directive(
|
||||||
ln,
|
ln,
|
||||||
|
@ -997,16 +997,13 @@ impl Config {
|
||||||
|
|
||||||
fn parse_env(nv: String) -> (String, String) {
|
fn parse_env(nv: String) -> (String, String) {
|
||||||
// nv is either FOO or FOO=BAR
|
// nv is either FOO or FOO=BAR
|
||||||
let mut strs: Vec<String> = nv.splitn(2, '=').map(str::to_owned).collect();
|
// FIXME(Zalathar): The form without `=` seems to be unused; should
|
||||||
|
// we drop support for it?
|
||||||
match strs.len() {
|
let (name, value) = nv.split_once('=').unwrap_or((&nv, ""));
|
||||||
1 => (strs.pop().unwrap(), String::new()),
|
// Trim whitespace from the name, so that `//@ exec-env: FOO=BAR`
|
||||||
2 => {
|
// sees the name as `FOO` and not ` FOO`.
|
||||||
let end = strs.pop().unwrap();
|
let name = name.trim();
|
||||||
(strs.pop().unwrap(), end)
|
(name.to_owned(), value.to_owned())
|
||||||
}
|
|
||||||
n => panic!("Expected 1 or 2 strings, not {}", n),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
|
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
|
||||||
|
|
|
@ -968,16 +968,16 @@ impl<'test> TestCx<'test> {
|
||||||
delete_after_success: bool,
|
delete_after_success: bool,
|
||||||
) -> ProcRes {
|
) -> ProcRes {
|
||||||
let prepare_env = |cmd: &mut Command| {
|
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 {
|
for (key, val) in &self.props.exec_env {
|
||||||
cmd.env(key, val);
|
cmd.env(key, val);
|
||||||
}
|
}
|
||||||
for (key, val) in env_extra {
|
for (key, val) in env_extra {
|
||||||
cmd.env(key, val);
|
cmd.env(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for key in &self.props.unset_exec_env {
|
||||||
|
cmd.env_remove(key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let proc_res = match &*self.config.target {
|
let proc_res = match &*self.config.target {
|
||||||
|
|
18
tests/rustdoc-ui/multi-par-footnote.rs
Normal file
18
tests/rustdoc-ui/multi-par-footnote.rs
Normal 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
|
||||||
|
}
|
5
tests/rustdoc-ui/multi-par-footnote.stdout
Normal file
5
tests/rustdoc-ui/multi-par-footnote.stdout
Normal 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
|
||||||
|
|
|
@ -63,7 +63,7 @@ fn dummy() {
|
||||||
// Malformed, where args?
|
// Malformed, where args?
|
||||||
#[autodiff]
|
#[autodiff]
|
||||||
pub fn f7(x: f64) {
|
pub fn f7(x: f64) {
|
||||||
//~^ ERROR autodiff must be applied to function
|
//~^ ERROR autodiff requires at least a name and mode
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ pub fn f8(x: f64) {
|
||||||
// Invalid attribute syntax
|
// Invalid attribute syntax
|
||||||
#[autodiff = ""]
|
#[autodiff = ""]
|
||||||
pub fn f9(x: f64) {
|
pub fn f9(x: f64) {
|
||||||
//~^ ERROR autodiff must be applied to function
|
//~^ ERROR autodiff requires at least a name and mode
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ error: autodiff must be applied to function
|
||||||
LL | let add_one_v2 = |x: u32| -> u32 { x + 1 };
|
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
|
--> $DIR/autodiff_illegal.rs:65:1
|
||||||
|
|
|
|
||||||
LL | / pub fn f7(x: f64) {
|
LL | / pub fn f7(x: f64) {
|
||||||
|
@ -80,7 +80,7 @@ LL | | unimplemented!()
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: autodiff must be applied to function
|
error: autodiff requires at least a name and mode
|
||||||
--> $DIR/autodiff_illegal.rs:79:1
|
--> $DIR/autodiff_illegal.rs:79:1
|
||||||
|
|
|
|
||||||
LL | / pub fn f9(x: f64) {
|
LL | / pub fn f9(x: f64) {
|
||||||
|
|
23
tests/ui/compiletest-self-test/trim-env-name.rs
Normal file
23
tests/ui/compiletest-self-test/trim-env-name.rs
Normal 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"));
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`.
|
|
4
tests/ui/parser/impl-parsing-2.rs
Normal file
4
tests/ui/parser/impl-parsing-2.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
impl ! {} // OK
|
||||||
|
|
||||||
|
default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
|
||||||
|
//~^ ERROR `default` is not followed by an item
|
18
tests/ui/parser/impl-parsing-2.stderr
Normal file
18
tests/ui/parser/impl-parsing-2.stderr
Normal 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
|
||||||
|
|
|
@ -2,9 +2,4 @@ impl ! {} // OK
|
||||||
impl ! where u8: Copy {} // OK
|
impl ! where u8: Copy {} // OK
|
||||||
|
|
||||||
impl Trait Type {} //~ ERROR missing `for` in a trait impl
|
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 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
|
|
||||||
|
|
|
@ -9,44 +9,11 @@ help: add `for` here
|
||||||
LL | impl Trait for Type {}
|
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
|
error: expected a trait, found type
|
||||||
--> $DIR/impl-parsing.rs:6:6
|
--> $DIR/impl-parsing.rs:5:6
|
||||||
|
|
|
|
||||||
LL | impl ?Sized for Type {}
|
LL | impl ?Sized for Type {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: expected a trait, found type
|
error: aborting due to 2 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,5 @@ fn main() {
|
||||||
let mut buffer = ArrayVec::new();
|
let mut buffer = ArrayVec::new();
|
||||||
let x = buffer.last().unwrap().0.clone();
|
let x = buffer.last().unwrap().0.clone();
|
||||||
//~^ ERROR type annotations needed
|
//~^ ERROR type annotations needed
|
||||||
//~| ERROR no field `0` on type `&_`
|
|
||||||
buffer.reverse();
|
buffer.reverse();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,6 @@ error[E0282]: type annotations needed
|
||||||
LL | let x = buffer.last().unwrap().0.clone();
|
LL | let x = buffer.last().unwrap().0.clone();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
|
||||||
|
|
||||||
error[E0609]: no field `0` on type `&_`
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/issue-65611.rs:59:36
|
|
||||||
|
|
|
||||||
LL | let x = buffer.last().unwrap().0.clone();
|
|
||||||
| ^ unknown field
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
For more information about this error, try `rustc --explain E0282`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0609.
|
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
|
||||||
|
|
|
@ -1123,8 +1123,8 @@ cc = ["@ZuseZ4"]
|
||||||
warn_non_default_branch.enable = true
|
warn_non_default_branch.enable = true
|
||||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||||
users_on_vacation = [
|
users_on_vacation = [
|
||||||
|
"fmease",
|
||||||
"jyn514",
|
"jyn514",
|
||||||
"saethlin",
|
|
||||||
"Noratrieb",
|
"Noratrieb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue