Auto merge of #92970 - matthiaskrgr:rollup-tcx7cfb, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #92487 (Fix unclosed boxes in pretty printing of TraitAlias) - #92581 (ARMv6K Horizon - Enable default libraries) - #92619 (Add diagnostic items for macros) - #92635 (rustdoc: Yet more intra-doc links cleanup) - #92646 (feat: rustc_pass_by_value lint attribute) - #92706 (Clarify explicitly that BTree{Map,Set} are ordered.) - #92710 (Include Projections when elaborating TypeOutlives) - #92746 (Parse `Ty?` as `Option<Ty>` and provide structured suggestion) - #92792 (rustdoc: fix intra-link for generic trait impls) - #92814 (remove unused FIXME) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
bd3cb52565
51 changed files with 907 additions and 363 deletions
|
@ -1357,9 +1357,7 @@ impl<'a> State<'a> {
|
||||||
self.bclose(item.span, empty);
|
self.bclose(item.span, empty);
|
||||||
}
|
}
|
||||||
ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
|
ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
|
||||||
self.head("");
|
self.head(visibility_qualified(&item.vis, "trait"));
|
||||||
self.print_visibility(&item.vis);
|
|
||||||
self.word_nbsp("trait");
|
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
self.print_generic_params(&generics.params);
|
self.print_generic_params(&generics.params);
|
||||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||||
|
@ -1377,6 +1375,8 @@ impl<'a> State<'a> {
|
||||||
self.print_type_bounds("=", &real_bounds);
|
self.print_type_bounds("=", &real_bounds);
|
||||||
self.print_where_clause(&generics.where_clause);
|
self.print_where_clause(&generics.where_clause);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
|
self.end(); // end inner head-block
|
||||||
|
self.end(); // end outer head-block
|
||||||
}
|
}
|
||||||
ast::ItemKind::MacCall(ref mac) => {
|
ast::ItemKind::MacCall(ref mac) => {
|
||||||
self.print_mac(mac);
|
self.print_mac(mac);
|
||||||
|
|
|
@ -623,6 +623,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
|
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
|
||||||
"language items are subject to change",
|
"language items are subject to change",
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_pass_by_value, Normal,
|
||||||
|
template!(Word), WarnFollowing,
|
||||||
|
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
|
||||||
|
),
|
||||||
BuiltinAttribute {
|
BuiltinAttribute {
|
||||||
name: sym::rustc_diagnostic_item,
|
name: sym::rustc_diagnostic_item,
|
||||||
type_: Normal,
|
type_: Normal,
|
||||||
|
|
|
@ -705,9 +705,7 @@ impl<'a> State<'a> {
|
||||||
self.bclose(item.span);
|
self.bclose(item.span);
|
||||||
}
|
}
|
||||||
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
|
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
|
||||||
self.head("");
|
self.head(visibility_qualified(&item.vis, "trait"));
|
||||||
self.print_visibility(&item.vis);
|
|
||||||
self.word_nbsp("trait");
|
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
self.print_generic_params(&generics.params);
|
self.print_generic_params(&generics.params);
|
||||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||||
|
@ -725,6 +723,8 @@ impl<'a> State<'a> {
|
||||||
self.print_bounds("=", real_bounds);
|
self.print_bounds("=", real_bounds);
|
||||||
self.print_where_clause(&generics.where_clause);
|
self.print_where_clause(&generics.where_clause);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
|
self.end(); // end inner head-block
|
||||||
|
self.end(); // end outer head-block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ann.post(self, AnnNode::Item(item))
|
self.ann.post(self, AnnNode::Item(item))
|
||||||
|
|
|
@ -9,7 +9,3 @@
|
||||||
pub mod bit_set;
|
pub mod bit_set;
|
||||||
pub mod interval;
|
pub mod interval;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
|
|
||||||
// FIXME(#56935): Work around ICEs during cross-compilation.
|
|
||||||
#[allow(unused)]
|
|
||||||
extern crate rustc_macros;
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
"cannot process registered region obligations in a snapshot"
|
"cannot process registered region obligations in a snapshot"
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!("process_registered_region_obligations()");
|
debug!(?param_env, "process_registered_region_obligations()");
|
||||||
|
|
||||||
let my_region_obligations = self.take_registered_region_obligations();
|
let my_region_obligations = self.take_registered_region_obligations();
|
||||||
|
|
||||||
|
@ -356,6 +356,8 @@ where
|
||||||
let trait_bounds: Vec<_> =
|
let trait_bounds: Vec<_> =
|
||||||
self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect();
|
self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect();
|
||||||
|
|
||||||
|
debug!(?trait_bounds);
|
||||||
|
|
||||||
// Compute the bounds we can derive from the environment. This
|
// Compute the bounds we can derive from the environment. This
|
||||||
// is an "approximate" match -- in some cases, these bounds
|
// is an "approximate" match -- in some cases, these bounds
|
||||||
// may not apply.
|
// may not apply.
|
||||||
|
|
|
@ -241,10 +241,19 @@ impl<'tcx> Elaborator<'tcx> {
|
||||||
|
|
||||||
Component::UnresolvedInferenceVariable(_) => None,
|
Component::UnresolvedInferenceVariable(_) => None,
|
||||||
|
|
||||||
Component::Projection(_) | Component::EscapingProjection(_) => {
|
Component::Projection(projection) => {
|
||||||
// We can probably do more here. This
|
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
|
||||||
// corresponds to a case like `<T as
|
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
|
||||||
// Foo<'a>>::U: 'b`.
|
let ty =
|
||||||
|
tcx.mk_projection(projection.item_def_id, projection.substs);
|
||||||
|
Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
|
||||||
|
ty, r_min,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
Component::EscapingProjection(_) => {
|
||||||
|
// We might be able to do more here, but we don't
|
||||||
|
// want to deal with escaping vars right now.
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,10 +5,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::{
|
use rustc_hir::{GenericArg, HirId, Item, ItemKind, Node, Path, PathSegment, QPath, Ty, TyKind};
|
||||||
GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
|
|
||||||
TyKind,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
|
@ -58,13 +55,6 @@ declare_tool_lint! {
|
||||||
report_in_external_macro: true
|
report_in_external_macro: true
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_tool_lint! {
|
|
||||||
pub rustc::TY_PASS_BY_REFERENCE,
|
|
||||||
Allow,
|
|
||||||
"passing `Ty` or `TyCtxt` by reference",
|
|
||||||
report_in_external_macro: true
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub rustc::USAGE_OF_QUALIFIED_TY,
|
pub rustc::USAGE_OF_QUALIFIED_TY,
|
||||||
Allow,
|
Allow,
|
||||||
|
@ -74,7 +64,6 @@ declare_tool_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(TyTyKind => [
|
declare_lint_pass!(TyTyKind => [
|
||||||
USAGE_OF_TY_TYKIND,
|
USAGE_OF_TY_TYKIND,
|
||||||
TY_PASS_BY_REFERENCE,
|
|
||||||
USAGE_OF_QUALIFIED_TY,
|
USAGE_OF_QUALIFIED_TY,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -131,26 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
|
|
||||||
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
|
|
||||||
if cx.tcx.impl_trait_ref(impl_did).is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) {
|
|
||||||
cx.struct_span_lint(TY_PASS_BY_REFERENCE, ty.span, |lint| {
|
|
||||||
lint.build(&format!("passing `{}` by reference", t))
|
|
||||||
.span_suggestion(
|
|
||||||
ty.span,
|
|
||||||
"try passing by value",
|
|
||||||
t,
|
|
||||||
// Changing type of function argument
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ mod non_ascii_idents;
|
||||||
mod non_fmt_panic;
|
mod non_fmt_panic;
|
||||||
mod nonstandard_style;
|
mod nonstandard_style;
|
||||||
mod noop_method_call;
|
mod noop_method_call;
|
||||||
|
mod pass_by_value;
|
||||||
mod passes;
|
mod passes;
|
||||||
mod redundant_semicolon;
|
mod redundant_semicolon;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
@ -85,6 +86,7 @@ use non_ascii_idents::*;
|
||||||
use non_fmt_panic::NonPanicFmt;
|
use non_fmt_panic::NonPanicFmt;
|
||||||
use nonstandard_style::*;
|
use nonstandard_style::*;
|
||||||
use noop_method_call::*;
|
use noop_method_call::*;
|
||||||
|
use pass_by_value::*;
|
||||||
use redundant_semicolon::*;
|
use redundant_semicolon::*;
|
||||||
use traits::*;
|
use traits::*;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
@ -490,6 +492,8 @@ fn register_internals(store: &mut LintStore) {
|
||||||
store.register_late_pass(|| Box::new(ExistingDocKeyword));
|
store.register_late_pass(|| Box::new(ExistingDocKeyword));
|
||||||
store.register_lints(&TyTyKind::get_lints());
|
store.register_lints(&TyTyKind::get_lints());
|
||||||
store.register_late_pass(|| Box::new(TyTyKind));
|
store.register_late_pass(|| Box::new(TyTyKind));
|
||||||
|
store.register_lints(&PassByValue::get_lints());
|
||||||
|
store.register_late_pass(|| Box::new(PassByValue));
|
||||||
store.register_group(
|
store.register_group(
|
||||||
false,
|
false,
|
||||||
"rustc::internal",
|
"rustc::internal",
|
||||||
|
@ -497,8 +501,8 @@ fn register_internals(store: &mut LintStore) {
|
||||||
vec![
|
vec![
|
||||||
LintId::of(DEFAULT_HASH_TYPES),
|
LintId::of(DEFAULT_HASH_TYPES),
|
||||||
LintId::of(USAGE_OF_TY_TYKIND),
|
LintId::of(USAGE_OF_TY_TYKIND),
|
||||||
|
LintId::of(PASS_BY_VALUE),
|
||||||
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||||
LintId::of(TY_PASS_BY_REFERENCE),
|
|
||||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||||
LintId::of(EXISTING_DOC_KEYWORD),
|
LintId::of(EXISTING_DOC_KEYWORD),
|
||||||
],
|
],
|
||||||
|
|
94
compiler/rustc_lint/src/pass_by_value.rs
Normal file
94
compiler/rustc_lint/src/pass_by_value.rs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::Res;
|
||||||
|
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
|
||||||
|
use rustc_middle::ty;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
|
declare_tool_lint! {
|
||||||
|
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to always be passed by value.
|
||||||
|
/// This is usually used for types that are thin wrappers around references, so there is no benefit to an extra
|
||||||
|
/// layer of indirection. (Example: `Ty` which is a reference to a `TyS`)
|
||||||
|
pub rustc::PASS_BY_VALUE,
|
||||||
|
Warn,
|
||||||
|
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
|
||||||
|
report_in_external_macro: true
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(PassByValue => [PASS_BY_VALUE]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
||||||
|
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
|
match &ty.kind {
|
||||||
|
TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
|
||||||
|
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
|
||||||
|
if cx.tcx.impl_trait_ref(impl_did).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
||||||
|
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
|
||||||
|
lint.build(&format!("passing `{}` by reference", t))
|
||||||
|
.span_suggestion(
|
||||||
|
ty.span,
|
||||||
|
"try passing by value",
|
||||||
|
t,
|
||||||
|
// Changing type of function argument
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
|
||||||
|
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||||
|
match path.res {
|
||||||
|
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
|
||||||
|
let name = cx.tcx.item_name(def_id).to_ident_string();
|
||||||
|
let path_segment = path.segments.last().unwrap();
|
||||||
|
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
|
||||||
|
}
|
||||||
|
Res::SelfTy(None, Some((did, _))) => {
|
||||||
|
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
|
||||||
|
if cx.tcx.has_attr(adt.did, sym::rustc_pass_by_value) {
|
||||||
|
return Some(cx.tcx.def_path_str_with_substs(adt.did, substs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
|
||||||
|
if let Some(args) = &segment.args {
|
||||||
|
let params = args
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| match arg {
|
||||||
|
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
|
||||||
|
GenericArg::Type(ty) => {
|
||||||
|
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default()
|
||||||
|
}
|
||||||
|
GenericArg::Const(c) => {
|
||||||
|
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default()
|
||||||
|
}
|
||||||
|
GenericArg::Infer(_) => String::from("_"),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !params.is_empty() {
|
||||||
|
return format!("<{}>", params.join(", "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::new()
|
||||||
|
}
|
|
@ -961,6 +961,7 @@ pub struct FreeRegionInfo {
|
||||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
|
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[rustc_diagnostic_item = "TyCtxt"]
|
#[rustc_diagnostic_item = "TyCtxt"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
|
||||||
pub struct TyCtxt<'tcx> {
|
pub struct TyCtxt<'tcx> {
|
||||||
gcx: &'tcx GlobalCtxt<'tcx>,
|
gcx: &'tcx GlobalCtxt<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,6 +464,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "Ty"]
|
#[rustc_diagnostic_item = "Ty"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
|
||||||
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||||
|
|
||||||
impl ty::EarlyBoundRegion {
|
impl ty::EarlyBoundRegion {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::pat::Expected;
|
use super::pat::Expected;
|
||||||
use super::ty::AllowPlus;
|
use super::ty::{AllowPlus, IsAsCast};
|
||||||
use super::{
|
use super::{
|
||||||
BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
|
BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
|
||||||
TokenExpectType, TokenType,
|
TokenExpectType, TokenType,
|
||||||
|
@ -1032,6 +1032,34 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
|
||||||
|
pub(super) fn maybe_recover_from_question_mark(
|
||||||
|
&mut self,
|
||||||
|
ty: P<Ty>,
|
||||||
|
is_as_cast: IsAsCast,
|
||||||
|
) -> P<Ty> {
|
||||||
|
if let IsAsCast::Yes = is_as_cast {
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
if self.token == token::Question {
|
||||||
|
self.bump();
|
||||||
|
self.struct_span_err(self.prev_token.span, "invalid `?` in type")
|
||||||
|
.span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
|
||||||
|
.multipart_suggestion(
|
||||||
|
"if you meant to express that the type might not contain a value, use the `Option` wrapper type",
|
||||||
|
vec![
|
||||||
|
(ty.span.shrink_to_lo(), "Option<".to_string()),
|
||||||
|
(self.prev_token.span, ">".to_string()),
|
||||||
|
],
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn maybe_recover_from_bad_type_plus(
|
pub(super) fn maybe_recover_from_bad_type_plus(
|
||||||
&mut self,
|
&mut self,
|
||||||
allow_plus: AllowPlus,
|
allow_plus: AllowPlus,
|
||||||
|
|
|
@ -682,7 +682,7 @@ impl<'a> Parser<'a> {
|
||||||
// Save the state of the parser before parsing type normally, in case there is a
|
// Save the state of the parser before parsing type normally, in case there is a
|
||||||
// LessThan comparison after this cast.
|
// LessThan comparison after this cast.
|
||||||
let parser_snapshot_before_type = self.clone();
|
let parser_snapshot_before_type = self.clone();
|
||||||
let cast_expr = match self.parse_ty_no_plus() {
|
let cast_expr = match self.parse_as_cast_ty() {
|
||||||
Ok(rhs) => mk_expr(self, lhs, rhs),
|
Ok(rhs) => mk_expr(self, lhs, rhs),
|
||||||
Err(mut type_err) => {
|
Err(mut type_err) => {
|
||||||
// Rewind to before attempting to parse the type with generics, to recover
|
// Rewind to before attempting to parse the type with generics, to recover
|
||||||
|
@ -808,7 +808,7 @@ impl<'a> Parser<'a> {
|
||||||
"casts cannot be followed by {}",
|
"casts cannot be followed by {}",
|
||||||
match with_postfix.kind {
|
match with_postfix.kind {
|
||||||
ExprKind::Index(_, _) => "indexing",
|
ExprKind::Index(_, _) => "indexing",
|
||||||
ExprKind::Try(_) => "?",
|
ExprKind::Try(_) => "`?`",
|
||||||
ExprKind::Field(_, _) => "a field access",
|
ExprKind::Field(_, _) => "a field access",
|
||||||
ExprKind::MethodCall(_, _, _) => "a method call",
|
ExprKind::MethodCall(_, _, _) => "a method call",
|
||||||
ExprKind::Call(_, _) => "a function call",
|
ExprKind::Call(_, _) => "a function call",
|
||||||
|
|
|
@ -44,6 +44,11 @@ pub(super) enum RecoverQPath {
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) enum IsAsCast {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
/// Signals whether parsing a type should recover `->`.
|
/// Signals whether parsing a type should recover `->`.
|
||||||
///
|
///
|
||||||
/// More specifically, when parsing a function like:
|
/// More specifically, when parsing a function like:
|
||||||
|
@ -100,6 +105,7 @@ impl<'a> Parser<'a> {
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +119,7 @@ impl<'a> Parser<'a> {
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
Some(ty_params),
|
Some(ty_params),
|
||||||
|
IsAsCast::No,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +133,7 @@ impl<'a> Parser<'a> {
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +150,22 @@ impl<'a> Parser<'a> {
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::Yes,
|
RecoverReturnSign::Yes,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
|
||||||
|
/// for better diagnostics involving `?`.
|
||||||
|
pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
|
||||||
|
self.parse_ty_common(
|
||||||
|
AllowPlus::No,
|
||||||
|
AllowCVariadic::No,
|
||||||
|
RecoverQPath::Yes,
|
||||||
|
RecoverReturnSign::Yes,
|
||||||
|
None,
|
||||||
|
IsAsCast::Yes,
|
||||||
|
)
|
||||||
|
}
|
||||||
/// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
|
/// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
|
||||||
pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
|
pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
|
||||||
self.parse_ty_common(
|
self.parse_ty_common(
|
||||||
|
@ -153,6 +174,7 @@ impl<'a> Parser<'a> {
|
||||||
RecoverQPath::Yes,
|
RecoverQPath::Yes,
|
||||||
RecoverReturnSign::OnlyFatArrow,
|
RecoverReturnSign::OnlyFatArrow,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +193,7 @@ impl<'a> Parser<'a> {
|
||||||
recover_qpath,
|
recover_qpath,
|
||||||
recover_return_sign,
|
recover_return_sign,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)?;
|
)?;
|
||||||
FnRetTy::Ty(ty)
|
FnRetTy::Ty(ty)
|
||||||
} else if recover_return_sign.can_recover(&self.token.kind) {
|
} else if recover_return_sign.can_recover(&self.token.kind) {
|
||||||
|
@ -191,6 +214,7 @@ impl<'a> Parser<'a> {
|
||||||
recover_qpath,
|
recover_qpath,
|
||||||
recover_return_sign,
|
recover_return_sign,
|
||||||
None,
|
None,
|
||||||
|
IsAsCast::No,
|
||||||
)?;
|
)?;
|
||||||
FnRetTy::Ty(ty)
|
FnRetTy::Ty(ty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,6 +229,7 @@ impl<'a> Parser<'a> {
|
||||||
recover_qpath: RecoverQPath,
|
recover_qpath: RecoverQPath,
|
||||||
recover_return_sign: RecoverReturnSign,
|
recover_return_sign: RecoverReturnSign,
|
||||||
ty_generics: Option<&Generics>,
|
ty_generics: Option<&Generics>,
|
||||||
|
is_as_cast: IsAsCast,
|
||||||
) -> PResult<'a, P<Ty>> {
|
) -> PResult<'a, P<Ty>> {
|
||||||
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
|
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
|
||||||
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
|
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
|
||||||
|
@ -280,6 +305,7 @@ impl<'a> Parser<'a> {
|
||||||
// Try to recover from use of `+` with incorrect priority.
|
// Try to recover from use of `+` with incorrect priority.
|
||||||
self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
|
self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
|
||||||
self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
|
self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
|
||||||
|
let ty = self.maybe_recover_from_question_mark(ty, is_as_cast);
|
||||||
self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
|
self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
||||||
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
|
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
|
||||||
|
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
|
||||||
sym::rustc_const_unstable
|
sym::rustc_const_unstable
|
||||||
| sym::rustc_const_stable
|
| sym::rustc_const_stable
|
||||||
| sym::unstable
|
| sym::unstable
|
||||||
|
@ -1066,6 +1067,24 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid
|
is_valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Warns against some misuses of `#[pass_by_value]`
|
||||||
|
fn check_pass_by_value(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
|
||||||
|
match target {
|
||||||
|
Target::Struct | Target::Enum | Target::TyAlias => true,
|
||||||
|
_ => {
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.struct_span_err(
|
||||||
|
attr.span,
|
||||||
|
"`pass_by_value` attribute should be applied to a struct, enum or type alias.",
|
||||||
|
)
|
||||||
|
.span_label(*span, "is not a struct, enum or type alias")
|
||||||
|
.emit();
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Warns against some misuses of `#[must_use]`
|
/// Warns against some misuses of `#[must_use]`
|
||||||
fn check_must_use(
|
fn check_must_use(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -336,8 +336,10 @@ symbols! {
|
||||||
asm_sym,
|
asm_sym,
|
||||||
asm_unwind,
|
asm_unwind,
|
||||||
assert,
|
assert,
|
||||||
|
assert_eq_macro,
|
||||||
assert_inhabited,
|
assert_inhabited,
|
||||||
assert_macro,
|
assert_macro,
|
||||||
|
assert_ne_macro,
|
||||||
assert_receiver_is_total_eq,
|
assert_receiver_is_total_eq,
|
||||||
assert_uninit_valid,
|
assert_uninit_valid,
|
||||||
assert_zero_valid,
|
assert_zero_valid,
|
||||||
|
@ -407,6 +409,7 @@ symbols! {
|
||||||
cfg_doctest,
|
cfg_doctest,
|
||||||
cfg_eval,
|
cfg_eval,
|
||||||
cfg_hide,
|
cfg_hide,
|
||||||
|
cfg_macro,
|
||||||
cfg_panic,
|
cfg_panic,
|
||||||
cfg_sanitize,
|
cfg_sanitize,
|
||||||
cfg_target_abi,
|
cfg_target_abi,
|
||||||
|
@ -434,15 +437,18 @@ symbols! {
|
||||||
coerce_unsized,
|
coerce_unsized,
|
||||||
cold,
|
cold,
|
||||||
column,
|
column,
|
||||||
|
column_macro,
|
||||||
compare_and_swap,
|
compare_and_swap,
|
||||||
compare_exchange,
|
compare_exchange,
|
||||||
compare_exchange_weak,
|
compare_exchange_weak,
|
||||||
compile_error,
|
compile_error,
|
||||||
|
compile_error_macro,
|
||||||
compiler_builtins,
|
compiler_builtins,
|
||||||
compiler_fence,
|
compiler_fence,
|
||||||
concat,
|
concat,
|
||||||
concat_bytes,
|
concat_bytes,
|
||||||
concat_idents,
|
concat_idents,
|
||||||
|
concat_macro,
|
||||||
conservative_impl_trait,
|
conservative_impl_trait,
|
||||||
console,
|
console,
|
||||||
const_allocate,
|
const_allocate,
|
||||||
|
@ -522,10 +528,13 @@ symbols! {
|
||||||
custom_inner_attributes,
|
custom_inner_attributes,
|
||||||
custom_test_frameworks,
|
custom_test_frameworks,
|
||||||
d,
|
d,
|
||||||
|
dbg_macro,
|
||||||
dead_code,
|
dead_code,
|
||||||
dealloc,
|
dealloc,
|
||||||
debug,
|
debug,
|
||||||
|
debug_assert_eq_macro,
|
||||||
debug_assert_macro,
|
debug_assert_macro,
|
||||||
|
debug_assert_ne_macro,
|
||||||
debug_assertions,
|
debug_assertions,
|
||||||
debug_struct,
|
debug_struct,
|
||||||
debug_trait_builder,
|
debug_trait_builder,
|
||||||
|
@ -597,6 +606,9 @@ symbols! {
|
||||||
encode,
|
encode,
|
||||||
end,
|
end,
|
||||||
env,
|
env,
|
||||||
|
env_macro,
|
||||||
|
eprint_macro,
|
||||||
|
eprintln_macro,
|
||||||
eq,
|
eq,
|
||||||
ermsb_target_feature,
|
ermsb_target_feature,
|
||||||
exact_div,
|
exact_div,
|
||||||
|
@ -644,6 +656,7 @@ symbols! {
|
||||||
field,
|
field,
|
||||||
field_init_shorthand,
|
field_init_shorthand,
|
||||||
file,
|
file,
|
||||||
|
file_macro,
|
||||||
fill,
|
fill,
|
||||||
finish,
|
finish,
|
||||||
flags,
|
flags,
|
||||||
|
@ -666,6 +679,7 @@ symbols! {
|
||||||
format,
|
format,
|
||||||
format_args,
|
format_args,
|
||||||
format_args_capture,
|
format_args_capture,
|
||||||
|
format_args_macro,
|
||||||
format_args_nl,
|
format_args_nl,
|
||||||
format_macro,
|
format_macro,
|
||||||
freeze,
|
freeze,
|
||||||
|
@ -732,7 +746,10 @@ symbols! {
|
||||||
in_band_lifetimes,
|
in_band_lifetimes,
|
||||||
include,
|
include,
|
||||||
include_bytes,
|
include_bytes,
|
||||||
|
include_bytes_macro,
|
||||||
|
include_macro,
|
||||||
include_str,
|
include_str,
|
||||||
|
include_str_macro,
|
||||||
inclusive_range_syntax,
|
inclusive_range_syntax,
|
||||||
index,
|
index,
|
||||||
index_mut,
|
index_mut,
|
||||||
|
@ -780,6 +797,7 @@ symbols! {
|
||||||
lifetime,
|
lifetime,
|
||||||
likely,
|
likely,
|
||||||
line,
|
line,
|
||||||
|
line_macro,
|
||||||
link,
|
link,
|
||||||
link_args,
|
link_args,
|
||||||
link_cfg,
|
link_cfg,
|
||||||
|
@ -823,6 +841,7 @@ symbols! {
|
||||||
masked,
|
masked,
|
||||||
match_beginning_vert,
|
match_beginning_vert,
|
||||||
match_default_bindings,
|
match_default_bindings,
|
||||||
|
matches_macro,
|
||||||
maxnumf32,
|
maxnumf32,
|
||||||
maxnumf64,
|
maxnumf64,
|
||||||
may_dangle,
|
may_dangle,
|
||||||
|
@ -859,6 +878,7 @@ symbols! {
|
||||||
modifiers,
|
modifiers,
|
||||||
module,
|
module,
|
||||||
module_path,
|
module_path,
|
||||||
|
module_path_macro,
|
||||||
more_qualified_paths,
|
more_qualified_paths,
|
||||||
more_struct_aliases,
|
more_struct_aliases,
|
||||||
movbe_target_feature,
|
movbe_target_feature,
|
||||||
|
@ -942,6 +962,7 @@ symbols! {
|
||||||
optin_builtin_traits,
|
optin_builtin_traits,
|
||||||
option,
|
option,
|
||||||
option_env,
|
option_env,
|
||||||
|
option_env_macro,
|
||||||
options,
|
options,
|
||||||
or,
|
or,
|
||||||
or_patterns,
|
or_patterns,
|
||||||
|
@ -1005,6 +1026,8 @@ symbols! {
|
||||||
prelude_import,
|
prelude_import,
|
||||||
preserves_flags,
|
preserves_flags,
|
||||||
primitive,
|
primitive,
|
||||||
|
print_macro,
|
||||||
|
println_macro,
|
||||||
proc_dash_macro: "proc-macro",
|
proc_dash_macro: "proc-macro",
|
||||||
proc_macro,
|
proc_macro,
|
||||||
proc_macro_attribute,
|
proc_macro_attribute,
|
||||||
|
@ -1147,6 +1170,7 @@ symbols! {
|
||||||
rustc_paren_sugar,
|
rustc_paren_sugar,
|
||||||
rustc_partition_codegened,
|
rustc_partition_codegened,
|
||||||
rustc_partition_reused,
|
rustc_partition_reused,
|
||||||
|
rustc_pass_by_value,
|
||||||
rustc_peek,
|
rustc_peek,
|
||||||
rustc_peek_definite_init,
|
rustc_peek_definite_init,
|
||||||
rustc_peek_liveness,
|
rustc_peek_liveness,
|
||||||
|
@ -1292,6 +1316,7 @@ symbols! {
|
||||||
str,
|
str,
|
||||||
str_alloc,
|
str_alloc,
|
||||||
stringify,
|
stringify,
|
||||||
|
stringify_macro,
|
||||||
struct_field_attributes,
|
struct_field_attributes,
|
||||||
struct_inherit,
|
struct_inherit,
|
||||||
struct_variant,
|
struct_variant,
|
||||||
|
@ -1335,6 +1360,8 @@ symbols! {
|
||||||
then_with,
|
then_with,
|
||||||
thread,
|
thread,
|
||||||
thread_local,
|
thread_local,
|
||||||
|
thread_local_macro,
|
||||||
|
todo_macro,
|
||||||
tool_attributes,
|
tool_attributes,
|
||||||
tool_lints,
|
tool_lints,
|
||||||
trace_macros,
|
trace_macros,
|
||||||
|
@ -1385,6 +1412,7 @@ symbols! {
|
||||||
underscore_imports,
|
underscore_imports,
|
||||||
underscore_lifetimes,
|
underscore_lifetimes,
|
||||||
uniform_paths,
|
uniform_paths,
|
||||||
|
unimplemented_macro,
|
||||||
unit,
|
unit,
|
||||||
universal_impl_trait,
|
universal_impl_trait,
|
||||||
unix,
|
unix,
|
||||||
|
@ -1393,6 +1421,7 @@ symbols! {
|
||||||
unpin,
|
unpin,
|
||||||
unreachable,
|
unreachable,
|
||||||
unreachable_code,
|
unreachable_code,
|
||||||
|
unreachable_macro,
|
||||||
unrestricted_attribute_tokens,
|
unrestricted_attribute_tokens,
|
||||||
unsafe_block_in_unsafe_fn,
|
unsafe_block_in_unsafe_fn,
|
||||||
unsafe_cell,
|
unsafe_cell,
|
||||||
|
@ -1423,6 +1452,7 @@ symbols! {
|
||||||
var,
|
var,
|
||||||
variant_count,
|
variant_count,
|
||||||
vec,
|
vec,
|
||||||
|
vec_macro,
|
||||||
version,
|
version,
|
||||||
vis,
|
vis,
|
||||||
visible_private_types,
|
visible_private_types,
|
||||||
|
@ -1447,7 +1477,9 @@ symbols! {
|
||||||
wrapping_sub,
|
wrapping_sub,
|
||||||
wreg,
|
wreg,
|
||||||
write_bytes,
|
write_bytes,
|
||||||
|
write_macro,
|
||||||
write_str,
|
write_str,
|
||||||
|
writeln_macro,
|
||||||
x87_reg,
|
x87_reg,
|
||||||
xer,
|
xer,
|
||||||
xmm_reg,
|
xmm_reg,
|
||||||
|
|
|
@ -36,6 +36,7 @@ pub fn target() -> Target {
|
||||||
features: "+vfp2".to_string(),
|
features: "+vfp2".to_string(),
|
||||||
pre_link_args,
|
pre_link_args,
|
||||||
exe_suffix: ".elf".to_string(),
|
exe_suffix: ".elf".to_string(),
|
||||||
|
no_default_libraries: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,7 +206,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
})?);
|
})?);
|
||||||
|
|
||||||
if let ty::Projection(..) = placeholder_self_ty.kind() {
|
if let ty::Projection(..) = placeholder_self_ty.kind() {
|
||||||
for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates {
|
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
|
||||||
|
debug!(?predicates, "projection predicates");
|
||||||
|
for predicate in predicates {
|
||||||
let normalized = normalize_with_depth_to(
|
let normalized = normalize_with_depth_to(
|
||||||
self,
|
self,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
|
||||||
// An empty map is represented either by the absence of a root node or by a
|
// An empty map is represented either by the absence of a root node or by a
|
||||||
// root node that is an empty leaf.
|
// root node that is an empty leaf.
|
||||||
|
|
||||||
/// A map based on a [B-Tree].
|
/// An ordered map based on a [B-Tree].
|
||||||
///
|
///
|
||||||
/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
|
/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
|
||||||
/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
|
/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
|
||||||
|
@ -68,6 +68,10 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
|
||||||
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
|
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
|
||||||
/// behavior.
|
/// behavior.
|
||||||
///
|
///
|
||||||
|
/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
|
||||||
|
/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
|
||||||
|
/// amortized constant time per item returned.
|
||||||
|
///
|
||||||
/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
|
/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
|
||||||
/// [`Cell`]: core::cell::Cell
|
/// [`Cell`]: core::cell::Cell
|
||||||
/// [`RefCell`]: core::cell::RefCell
|
/// [`RefCell`]: core::cell::RefCell
|
||||||
|
|
|
@ -15,7 +15,7 @@ use super::Recover;
|
||||||
|
|
||||||
// FIXME(conventions): implement bounded iterators
|
// FIXME(conventions): implement bounded iterators
|
||||||
|
|
||||||
/// A set based on a B-Tree.
|
/// An ordered set based on a B-Tree.
|
||||||
///
|
///
|
||||||
/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance
|
/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance
|
||||||
/// benefits and drawbacks.
|
/// benefits and drawbacks.
|
||||||
|
@ -27,6 +27,9 @@ use super::Recover;
|
||||||
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
|
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
|
||||||
/// behavior.
|
/// behavior.
|
||||||
///
|
///
|
||||||
|
/// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
|
||||||
|
/// logarithmic and amortized constant time per item returned.
|
||||||
|
///
|
||||||
/// [`Ord`]: core::cmp::Ord
|
/// [`Ord`]: core::cmp::Ord
|
||||||
/// [`Cell`]: core::cell::Cell
|
/// [`Cell`]: core::cell::Cell
|
||||||
/// [`RefCell`]: core::cell::RefCell
|
/// [`RefCell`]: core::cell::RefCell
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub mod vec_deque;
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub mod btree_map {
|
pub mod btree_map {
|
||||||
//! A map based on a B-Tree.
|
//! An ordered map based on a B-Tree.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use super::btree::map::*;
|
pub use super::btree::map::*;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ pub mod btree_map {
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub mod btree_set {
|
pub mod btree_set {
|
||||||
//! A set based on a B-Tree.
|
//! An ordered set based on a B-Tree.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use super::btree::set::*;
|
pub use super::btree::set::*;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_diagnostic_item = "vec_macro"]
|
||||||
#[allow_internal_unstable(box_syntax, liballoc_internals)]
|
#[allow_internal_unstable(box_syntax, liballoc_internals)]
|
||||||
macro_rules! vec {
|
macro_rules! vec {
|
||||||
() => (
|
() => (
|
||||||
|
|
|
@ -31,6 +31,7 @@ macro_rules! panic {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "assert_eq_macro")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
macro_rules! assert_eq {
|
macro_rules! assert_eq {
|
||||||
($left:expr, $right:expr $(,)?) => ({
|
($left:expr, $right:expr $(,)?) => ({
|
||||||
|
@ -80,6 +81,7 @@ macro_rules! assert_eq {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "assert_ne", since = "1.13.0")]
|
#[stable(feature = "assert_ne", since = "1.13.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "assert_ne_macro")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
macro_rules! assert_ne {
|
macro_rules! assert_ne {
|
||||||
($left:expr, $right:expr $(,)?) => ({
|
($left:expr, $right:expr $(,)?) => ({
|
||||||
|
@ -236,6 +238,7 @@ macro_rules! debug_assert {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_eq_macro")]
|
||||||
macro_rules! debug_assert_eq {
|
macro_rules! debug_assert_eq {
|
||||||
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
|
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
|
||||||
}
|
}
|
||||||
|
@ -261,6 +264,7 @@ macro_rules! debug_assert_eq {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "assert_ne", since = "1.13.0")]
|
#[stable(feature = "assert_ne", since = "1.13.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_ne_macro")]
|
||||||
macro_rules! debug_assert_ne {
|
macro_rules! debug_assert_ne {
|
||||||
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
|
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
|
||||||
}
|
}
|
||||||
|
@ -320,6 +324,7 @@ pub macro debug_assert_matches($($arg:tt)*) {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "matches_macro", since = "1.42.0")]
|
#[stable(feature = "matches_macro", since = "1.42.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")]
|
||||||
macro_rules! matches {
|
macro_rules! matches {
|
||||||
($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
|
($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
|
||||||
match $expression {
|
match $expression {
|
||||||
|
@ -475,6 +480,7 @@ macro_rules! r#try {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")]
|
||||||
macro_rules! write {
|
macro_rules! write {
|
||||||
($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
|
($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
|
||||||
}
|
}
|
||||||
|
@ -525,6 +531,7 @@ macro_rules! write {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "writeln_macro")]
|
||||||
#[allow_internal_unstable(format_args_nl)]
|
#[allow_internal_unstable(format_args_nl)]
|
||||||
macro_rules! writeln {
|
macro_rules! writeln {
|
||||||
($dst:expr $(,)?) => (
|
($dst:expr $(,)?) => (
|
||||||
|
@ -589,6 +596,7 @@ macro_rules! writeln {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "unreachable_macro")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
macro_rules! unreachable {
|
macro_rules! unreachable {
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -675,6 +683,7 @@ macro_rules! unreachable {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "unimplemented_macro")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
macro_rules! unimplemented {
|
macro_rules! unimplemented {
|
||||||
() => ($crate::panicking::panic("not implemented"));
|
() => ($crate::panicking::panic("not implemented"));
|
||||||
|
@ -737,6 +746,7 @@ macro_rules! unimplemented {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "todo_macro", since = "1.40.0")]
|
#[stable(feature = "todo_macro", since = "1.40.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "todo_macro")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
macro_rules! todo {
|
macro_rules! todo {
|
||||||
() => ($crate::panicking::panic("not yet implemented"));
|
() => ($crate::panicking::panic("not yet implemented"));
|
||||||
|
@ -786,6 +796,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "compile_error_macro", since = "1.20.0")]
|
#[stable(feature = "compile_error_macro", since = "1.20.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "compile_error_macro")]
|
||||||
macro_rules! compile_error {
|
macro_rules! compile_error {
|
||||||
($msg:expr $(,)?) => {{ /* compiler built-in */ }};
|
($msg:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
@ -835,6 +846,7 @@ pub(crate) mod builtin {
|
||||||
/// assert_eq!(s, format!("hello {}", "world"));
|
/// assert_eq!(s, format!("hello {}", "world"));
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "format_args_macro")]
|
||||||
#[allow_internal_unsafe]
|
#[allow_internal_unsafe]
|
||||||
#[allow_internal_unstable(fmt_internals)]
|
#[allow_internal_unstable(fmt_internals)]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
|
@ -905,6 +917,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "env_macro")]
|
||||||
macro_rules! env {
|
macro_rules! env {
|
||||||
($name:expr $(,)?) => {{ /* compiler built-in */ }};
|
($name:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }};
|
($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
|
@ -930,6 +943,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "option_env_macro")]
|
||||||
macro_rules! option_env {
|
macro_rules! option_env {
|
||||||
($name:expr $(,)?) => {{ /* compiler built-in */ }};
|
($name:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
@ -1015,6 +1029,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "concat_macro")]
|
||||||
macro_rules! concat {
|
macro_rules! concat {
|
||||||
($($e:expr),* $(,)?) => {{ /* compiler built-in */ }};
|
($($e:expr),* $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
@ -1040,6 +1055,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "line_macro")]
|
||||||
macro_rules! line {
|
macro_rules! line {
|
||||||
() => {
|
() => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1079,6 +1095,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "column_macro")]
|
||||||
macro_rules! column {
|
macro_rules! column {
|
||||||
() => {
|
() => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1104,6 +1121,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "file_macro")]
|
||||||
macro_rules! file {
|
macro_rules! file {
|
||||||
() => {
|
() => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1128,6 +1146,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "stringify_macro")]
|
||||||
macro_rules! stringify {
|
macro_rules! stringify {
|
||||||
($($t:tt)*) => {
|
($($t:tt)*) => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1169,6 +1188,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "include_str_macro")]
|
||||||
macro_rules! include_str {
|
macro_rules! include_str {
|
||||||
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
@ -1208,6 +1228,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "include_bytes_macro")]
|
||||||
macro_rules! include_bytes {
|
macro_rules! include_bytes {
|
||||||
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
@ -1232,6 +1253,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "module_path_macro")]
|
||||||
macro_rules! module_path {
|
macro_rules! module_path {
|
||||||
() => {
|
() => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1265,6 +1287,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "cfg_macro")]
|
||||||
macro_rules! cfg {
|
macro_rules! cfg {
|
||||||
($($cfg:tt)*) => {
|
($($cfg:tt)*) => {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
|
@ -1315,6 +1338,7 @@ pub(crate) mod builtin {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "include_macro")]
|
||||||
macro_rules! include {
|
macro_rules! include {
|
||||||
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
($file:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ macro_rules! panic {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")]
|
||||||
#[allow_internal_unstable(print_internals)]
|
#[allow_internal_unstable(print_internals)]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
|
($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
|
||||||
|
@ -90,6 +91,7 @@ macro_rules! print {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")]
|
||||||
#[allow_internal_unstable(print_internals, format_args_nl)]
|
#[allow_internal_unstable(print_internals, format_args_nl)]
|
||||||
macro_rules! println {
|
macro_rules! println {
|
||||||
() => ($crate::print!("\n"));
|
() => ($crate::print!("\n"));
|
||||||
|
@ -121,6 +123,7 @@ macro_rules! println {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "eprint", since = "1.19.0")]
|
#[stable(feature = "eprint", since = "1.19.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")]
|
||||||
#[allow_internal_unstable(print_internals)]
|
#[allow_internal_unstable(print_internals)]
|
||||||
macro_rules! eprint {
|
macro_rules! eprint {
|
||||||
($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
|
($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
|
||||||
|
@ -149,6 +152,7 @@ macro_rules! eprint {
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "eprint", since = "1.19.0")]
|
#[stable(feature = "eprint", since = "1.19.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")]
|
||||||
#[allow_internal_unstable(print_internals, format_args_nl)]
|
#[allow_internal_unstable(print_internals, format_args_nl)]
|
||||||
macro_rules! eprintln {
|
macro_rules! eprintln {
|
||||||
() => ($crate::eprint!("\n"));
|
() => ($crate::eprint!("\n"));
|
||||||
|
@ -282,6 +286,7 @@ macro_rules! eprintln {
|
||||||
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
|
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
|
||||||
/// [`log`]: https://crates.io/crates/log
|
/// [`log`]: https://crates.io/crates/log
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "dbg_macro")]
|
||||||
#[stable(feature = "dbg_macro", since = "1.32.0")]
|
#[stable(feature = "dbg_macro", since = "1.32.0")]
|
||||||
macro_rules! dbg {
|
macro_rules! dbg {
|
||||||
// NOTE: We cannot use `concat!` to make a static string as a format argument
|
// NOTE: We cannot use `concat!` to make a static string as a format argument
|
||||||
|
|
|
@ -142,6 +142,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
|
||||||
/// [`std::thread::LocalKey`]: crate::thread::LocalKey
|
/// [`std::thread::LocalKey`]: crate::thread::LocalKey
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
|
||||||
#[allow_internal_unstable(thread_local_internals)]
|
#[allow_internal_unstable(thread_local_internals)]
|
||||||
macro_rules! thread_local {
|
macro_rules! thread_local {
|
||||||
// empty (base case for the recursion)
|
// empty (base case for the recursion)
|
||||||
|
|
|
@ -6,13 +6,12 @@ use rustc_ast as ast;
|
||||||
use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet};
|
use rustc_data_structures::{fx::FxHashMap, stable_set::FxHashSet};
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
use rustc_expand::base::SyntaxExtensionKind;
|
use rustc_expand::base::SyntaxExtensionKind;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::{
|
use rustc_hir::def::{
|
||||||
DefKind,
|
DefKind,
|
||||||
Namespace::{self, *},
|
Namespace::{self, *},
|
||||||
PerNS,
|
PerNS,
|
||||||
};
|
};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID};
|
||||||
use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
|
use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
|
||||||
use rustc_middle::{bug, span_bug, ty};
|
use rustc_middle::{bug, span_bug, ty};
|
||||||
use rustc_resolve::ParentScope;
|
use rustc_resolve::ParentScope;
|
||||||
|
@ -109,6 +108,45 @@ impl Res {
|
||||||
Res::Primitive(_) => None,
|
Res::Primitive(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for error reporting.
|
||||||
|
fn disambiguator_suggestion(self) -> Suggestion {
|
||||||
|
let kind = match self {
|
||||||
|
Res::Primitive(_) => return Suggestion::Prefix("prim"),
|
||||||
|
Res::Def(kind, _) => kind,
|
||||||
|
};
|
||||||
|
if kind == DefKind::Macro(MacroKind::Bang) {
|
||||||
|
return Suggestion::Macro;
|
||||||
|
} else if kind == DefKind::Fn || kind == DefKind::AssocFn {
|
||||||
|
return Suggestion::Function;
|
||||||
|
} else if kind == DefKind::Field {
|
||||||
|
return Suggestion::RemoveDisambiguator;
|
||||||
|
}
|
||||||
|
|
||||||
|
let prefix = match kind {
|
||||||
|
DefKind::Struct => "struct",
|
||||||
|
DefKind::Enum => "enum",
|
||||||
|
DefKind::Trait => "trait",
|
||||||
|
DefKind::Union => "union",
|
||||||
|
DefKind::Mod => "mod",
|
||||||
|
DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => {
|
||||||
|
"const"
|
||||||
|
}
|
||||||
|
DefKind::Static => "static",
|
||||||
|
DefKind::Macro(MacroKind::Derive) => "derive",
|
||||||
|
// Now handle things that don't have a specific disambiguator
|
||||||
|
_ => match kind
|
||||||
|
.ns()
|
||||||
|
.expect("tried to calculate a disambiguator for a def without a namespace?")
|
||||||
|
{
|
||||||
|
Namespace::TypeNS => "type",
|
||||||
|
Namespace::ValueNS => "value",
|
||||||
|
Namespace::MacroNS => "macro",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Suggestion::Prefix(prefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<ResolveRes> for Res {
|
impl TryFrom<ResolveRes> for Res {
|
||||||
|
@ -346,7 +384,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||||
/// In particular, this will return an error whenever there aren't three
|
/// In particular, this will return an error whenever there aren't three
|
||||||
/// full path segments left in the link.
|
/// full path segments left in the link.
|
||||||
///
|
///
|
||||||
/// [enum struct variant]: hir::VariantData::Struct
|
/// [enum struct variant]: rustc_hir::VariantData::Struct
|
||||||
fn variant_field<'path>(
|
fn variant_field<'path>(
|
||||||
&self,
|
&self,
|
||||||
path_str: &'path str,
|
path_str: &'path str,
|
||||||
|
@ -667,10 +705,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns:
|
/// Resolve an associated item, returning its containing page's `Res`
|
||||||
/// - None if no associated item was found
|
/// and the fragment targeting the associated item on its page.
|
||||||
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
|
|
||||||
/// - Some((_, _, None)) otherwise
|
|
||||||
fn resolve_associated_item(
|
fn resolve_associated_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
root_res: Res,
|
root_res: Res,
|
||||||
|
@ -903,7 +939,18 @@ fn traits_implemented_by<'a>(
|
||||||
ty
|
ty
|
||||||
);
|
);
|
||||||
// Fast path: if this is a primitive simple `==` will work
|
// Fast path: if this is a primitive simple `==` will work
|
||||||
let saw_impl = impl_type == ty;
|
// NOTE: the `match` is necessary; see #92662.
|
||||||
|
// this allows us to ignore generics because the user input
|
||||||
|
// may not include the generic placeholders
|
||||||
|
// e.g. this allows us to match Foo (user comment) with Foo<T> (actual type)
|
||||||
|
let saw_impl = impl_type == ty
|
||||||
|
|| match (impl_type.kind(), ty.kind()) {
|
||||||
|
(ty::Adt(impl_def, _), ty::Adt(ty_def, _)) => {
|
||||||
|
debug!("impl def_id: {:?}, ty def_id: {:?}", impl_def.did, ty_def.did);
|
||||||
|
impl_def.did == ty_def.did
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
if saw_impl { Some(trait_) } else { None }
|
if saw_impl { Some(trait_) } else { None }
|
||||||
})
|
})
|
||||||
|
@ -958,17 +1005,7 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
self.cx.tcx.parent(did)
|
self.cx.tcx.parent(did)
|
||||||
}
|
}
|
||||||
Some(did) => match self.cx.tcx.parent(did) {
|
Some(did) => Some(did),
|
||||||
// HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
|
|
||||||
// Fixing this breaks `fn render_deref_methods`.
|
|
||||||
// As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
|
|
||||||
// regardless of what rustdoc wants to call it.
|
|
||||||
Some(parent) => {
|
|
||||||
let parent_kind = self.cx.tcx.def_kind(parent);
|
|
||||||
Some(if parent_kind == DefKind::Impl { parent } else { did })
|
|
||||||
}
|
|
||||||
None => Some(did),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
|
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
|
||||||
|
@ -1277,79 +1314,9 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let report_mismatch = |specified: Disambiguator, resolved: Disambiguator| {
|
|
||||||
// The resolved item did not match the disambiguator; give a better error than 'not found'
|
|
||||||
let msg = format!("incompatible link kind for `{}`", path_str);
|
|
||||||
let callback = |diag: &mut DiagnosticBuilder<'_>, sp: Option<rustc_span::Span>| {
|
|
||||||
let note = format!(
|
|
||||||
"this link resolved to {} {}, which is not {} {}",
|
|
||||||
resolved.article(),
|
|
||||||
resolved.descr(),
|
|
||||||
specified.article(),
|
|
||||||
specified.descr()
|
|
||||||
);
|
|
||||||
if let Some(sp) = sp {
|
|
||||||
diag.span_label(sp, ¬e);
|
|
||||||
} else {
|
|
||||||
diag.note(¬e);
|
|
||||||
}
|
|
||||||
suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
|
|
||||||
};
|
|
||||||
report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
let verify = |kind: DefKind, id: DefId| {
|
|
||||||
let (kind, id) = if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
|
|
||||||
(self.cx.tcx.def_kind(id), id)
|
|
||||||
} else {
|
|
||||||
(kind, id)
|
|
||||||
};
|
|
||||||
debug!("intra-doc link to {} resolved to {:?} (id: {:?})", path_str, res, id);
|
|
||||||
|
|
||||||
// Disallow e.g. linking to enums with `struct@`
|
|
||||||
debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
|
|
||||||
match (kind, disambiguator) {
|
|
||||||
| (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
|
|
||||||
// NOTE: this allows 'method' to mean both normal functions and associated functions
|
|
||||||
// This can't cause ambiguity because both are in the same namespace.
|
|
||||||
| (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
|
|
||||||
// These are namespaces; allow anything in the namespace to match
|
|
||||||
| (_, Some(Disambiguator::Namespace(_)))
|
|
||||||
// If no disambiguator given, allow anything
|
|
||||||
| (_, None)
|
|
||||||
// All of these are valid, so do nothing
|
|
||||||
=> {}
|
|
||||||
(actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
|
|
||||||
(_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
|
|
||||||
report_mismatch(specified, Disambiguator::Kind(kind));
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
|
|
||||||
if let Some((src_id, dst_id)) = id
|
|
||||||
.as_local()
|
|
||||||
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
|
|
||||||
// would presumably panic if a fake `DefIndex` were passed.
|
|
||||||
.and_then(|dst_id| {
|
|
||||||
item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
|
|
||||||
})
|
|
||||||
{
|
|
||||||
if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
|
|
||||||
&& !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id)
|
|
||||||
{
|
|
||||||
privacy_error(self.cx, &diag_info, path_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
};
|
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Res::Primitive(prim) => {
|
Res::Primitive(prim) => {
|
||||||
if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
|
if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
|
||||||
let kind = self.cx.tcx.def_kind(id);
|
|
||||||
|
|
||||||
// We're actually resolving an associated item of a primitive, so we need to
|
// We're actually resolving an associated item of a primitive, so we need to
|
||||||
// verify the disambiguator (if any) matches the type of the associated item.
|
// verify the disambiguator (if any) matches the type of the associated item.
|
||||||
// This case should really follow the same flow as the `Res::Def` branch below,
|
// This case should really follow the same flow as the `Res::Def` branch below,
|
||||||
|
@ -1358,7 +1325,16 @@ impl LinkCollector<'_, '_> {
|
||||||
// doesn't allow statements like `use str::trim;`, making this a (hopefully)
|
// doesn't allow statements like `use str::trim;`, making this a (hopefully)
|
||||||
// valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
|
// valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
|
||||||
// for discussion on the matter.
|
// for discussion on the matter.
|
||||||
verify(kind, id)?;
|
let kind = self.cx.tcx.def_kind(id);
|
||||||
|
self.verify_disambiguator(
|
||||||
|
path_str,
|
||||||
|
&ori_link,
|
||||||
|
kind,
|
||||||
|
id,
|
||||||
|
disambiguator,
|
||||||
|
item,
|
||||||
|
&diag_info,
|
||||||
|
)?;
|
||||||
|
|
||||||
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
|
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
|
||||||
// However I'm not sure how to check that across crates.
|
// However I'm not sure how to check that across crates.
|
||||||
|
@ -1372,7 +1348,9 @@ impl LinkCollector<'_, '_> {
|
||||||
match disambiguator {
|
match disambiguator {
|
||||||
Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
|
Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
|
||||||
Some(other) => {
|
Some(other) => {
|
||||||
report_mismatch(other, Disambiguator::Primitive);
|
self.report_disambiguator_mismatch(
|
||||||
|
path_str, &ori_link, other, res, &diag_info,
|
||||||
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1386,13 +1364,106 @@ impl LinkCollector<'_, '_> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Res::Def(kind, id) => {
|
Res::Def(kind, id) => {
|
||||||
verify(kind, id)?;
|
let (kind_for_dis, id_for_dis) =
|
||||||
|
if let Some(UrlFragment::Item(ItemFragment(_, id))) = fragment {
|
||||||
|
(self.cx.tcx.def_kind(id), id)
|
||||||
|
} else {
|
||||||
|
(kind, id)
|
||||||
|
};
|
||||||
|
self.verify_disambiguator(
|
||||||
|
path_str,
|
||||||
|
&ori_link,
|
||||||
|
kind_for_dis,
|
||||||
|
id_for_dis,
|
||||||
|
disambiguator,
|
||||||
|
item,
|
||||||
|
&diag_info,
|
||||||
|
)?;
|
||||||
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
|
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
|
||||||
Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
|
Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_disambiguator(
|
||||||
|
&self,
|
||||||
|
path_str: &str,
|
||||||
|
ori_link: &MarkdownLink,
|
||||||
|
kind: DefKind,
|
||||||
|
id: DefId,
|
||||||
|
disambiguator: Option<Disambiguator>,
|
||||||
|
item: &Item,
|
||||||
|
diag_info: &DiagnosticInfo<'_>,
|
||||||
|
) -> Option<()> {
|
||||||
|
debug!("intra-doc link to {} resolved to {:?}", path_str, (kind, id));
|
||||||
|
|
||||||
|
// Disallow e.g. linking to enums with `struct@`
|
||||||
|
debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
|
||||||
|
match (kind, disambiguator) {
|
||||||
|
| (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
|
||||||
|
// NOTE: this allows 'method' to mean both normal functions and associated functions
|
||||||
|
// This can't cause ambiguity because both are in the same namespace.
|
||||||
|
| (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
|
||||||
|
// These are namespaces; allow anything in the namespace to match
|
||||||
|
| (_, Some(Disambiguator::Namespace(_)))
|
||||||
|
// If no disambiguator given, allow anything
|
||||||
|
| (_, None)
|
||||||
|
// All of these are valid, so do nothing
|
||||||
|
=> {}
|
||||||
|
(actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
|
||||||
|
(_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
|
||||||
|
self.report_disambiguator_mismatch(path_str,ori_link,specified, Res::Def(kind, id),diag_info);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
|
||||||
|
if let Some((src_id, dst_id)) = id
|
||||||
|
.as_local()
|
||||||
|
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
|
||||||
|
// would presumably panic if a fake `DefIndex` were passed.
|
||||||
|
.and_then(|dst_id| {
|
||||||
|
item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
|
||||||
|
&& !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id)
|
||||||
|
{
|
||||||
|
privacy_error(self.cx, diag_info, path_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_disambiguator_mismatch(
|
||||||
|
&self,
|
||||||
|
path_str: &str,
|
||||||
|
ori_link: &MarkdownLink,
|
||||||
|
specified: Disambiguator,
|
||||||
|
resolved: Res,
|
||||||
|
diag_info: &DiagnosticInfo<'_>,
|
||||||
|
) {
|
||||||
|
// The resolved item did not match the disambiguator; give a better error than 'not found'
|
||||||
|
let msg = format!("incompatible link kind for `{}`", path_str);
|
||||||
|
let callback = |diag: &mut DiagnosticBuilder<'_>, sp: Option<rustc_span::Span>| {
|
||||||
|
let note = format!(
|
||||||
|
"this link resolved to {} {}, which is not {} {}",
|
||||||
|
resolved.article(),
|
||||||
|
resolved.descr(),
|
||||||
|
specified.article(),
|
||||||
|
specified.descr(),
|
||||||
|
);
|
||||||
|
if let Some(sp) = sp {
|
||||||
|
diag.span_label(sp, ¬e);
|
||||||
|
} else {
|
||||||
|
diag.note(¬e);
|
||||||
|
}
|
||||||
|
suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
|
||||||
|
};
|
||||||
|
report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, callback);
|
||||||
|
}
|
||||||
|
|
||||||
fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &MarkdownLink, item: &Item) {
|
fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &MarkdownLink, item: &Item) {
|
||||||
let span =
|
let span =
|
||||||
super::source_span_for_markdown_range(self.cx.tcx, dox, &ori_link.range, &item.attrs)
|
super::source_span_for_markdown_range(self.cx.tcx, dox, &ori_link.range, &item.attrs)
|
||||||
|
@ -1413,7 +1484,6 @@ impl LinkCollector<'_, '_> {
|
||||||
diag: DiagnosticInfo<'_>,
|
diag: DiagnosticInfo<'_>,
|
||||||
cache_resolution_failure: bool,
|
cache_resolution_failure: bool,
|
||||||
) -> Option<(Res, Option<UrlFragment>)> {
|
) -> Option<(Res, Option<UrlFragment>)> {
|
||||||
// Try to look up both the result and the corresponding side channel value
|
|
||||||
if let Some(ref cached) = self.visited_links.get(&key) {
|
if let Some(ref cached) = self.visited_links.get(&key) {
|
||||||
match cached {
|
match cached {
|
||||||
Some(cached) => {
|
Some(cached) => {
|
||||||
|
@ -1686,53 +1756,6 @@ impl Disambiguator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_res(res: Res) -> Self {
|
|
||||||
match res {
|
|
||||||
Res::Def(kind, _) => Disambiguator::Kind(kind),
|
|
||||||
Res::Primitive(_) => Disambiguator::Primitive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Used for error reporting.
|
|
||||||
fn suggestion(self) -> Suggestion {
|
|
||||||
let kind = match self {
|
|
||||||
Disambiguator::Primitive => return Suggestion::Prefix("prim"),
|
|
||||||
Disambiguator::Kind(kind) => kind,
|
|
||||||
Disambiguator::Namespace(_) => panic!("display_for cannot be used on namespaces"),
|
|
||||||
};
|
|
||||||
if kind == DefKind::Macro(MacroKind::Bang) {
|
|
||||||
return Suggestion::Macro;
|
|
||||||
} else if kind == DefKind::Fn || kind == DefKind::AssocFn {
|
|
||||||
return Suggestion::Function;
|
|
||||||
} else if kind == DefKind::Field {
|
|
||||||
return Suggestion::RemoveDisambiguator;
|
|
||||||
}
|
|
||||||
|
|
||||||
let prefix = match kind {
|
|
||||||
DefKind::Struct => "struct",
|
|
||||||
DefKind::Enum => "enum",
|
|
||||||
DefKind::Trait => "trait",
|
|
||||||
DefKind::Union => "union",
|
|
||||||
DefKind::Mod => "mod",
|
|
||||||
DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => {
|
|
||||||
"const"
|
|
||||||
}
|
|
||||||
DefKind::Static => "static",
|
|
||||||
DefKind::Macro(MacroKind::Derive) => "derive",
|
|
||||||
// Now handle things that don't have a specific disambiguator
|
|
||||||
_ => match kind
|
|
||||||
.ns()
|
|
||||||
.expect("tried to calculate a disambiguator for a def without a namespace?")
|
|
||||||
{
|
|
||||||
Namespace::TypeNS => "type",
|
|
||||||
Namespace::ValueNS => "value",
|
|
||||||
Namespace::MacroNS => "macro",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Suggestion::Prefix(prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ns(self) -> Namespace {
|
fn ns(self) -> Namespace {
|
||||||
match self {
|
match self {
|
||||||
Self::Namespace(n) => n,
|
Self::Namespace(n) => n,
|
||||||
|
@ -1754,9 +1777,9 @@ impl Disambiguator {
|
||||||
fn descr(self) -> &'static str {
|
fn descr(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Namespace(n) => n.descr(),
|
Self::Namespace(n) => n.descr(),
|
||||||
// HACK(jynelson): by looking at the source I saw the DefId we pass
|
// HACK(jynelson): the source of `DefKind::descr` only uses the DefId for
|
||||||
// for `expected.descr()` doesn't matter, since it's not a crate
|
// printing "module" vs "crate" so using the wrong ID is not a huge problem
|
||||||
Self::Kind(k) => k.descr(DefId::local(hir::def_id::DefIndex::from_usize(0))),
|
Self::Kind(k) => k.descr(CRATE_DEF_ID.to_def_id()),
|
||||||
Self::Primitive => "builtin type",
|
Self::Primitive => "builtin type",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2080,16 +2103,7 @@ fn resolution_failure(
|
||||||
ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
|
ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
|
||||||
ResolutionFailure::Dummy => continue,
|
ResolutionFailure::Dummy => continue,
|
||||||
ResolutionFailure::WrongNamespace { res, expected_ns } => {
|
ResolutionFailure::WrongNamespace { res, expected_ns } => {
|
||||||
if let Res::Def(kind, _) = res {
|
suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
|
||||||
let disambiguator = Disambiguator::Kind(kind);
|
|
||||||
suggest_disambiguator(
|
|
||||||
disambiguator,
|
|
||||||
diag,
|
|
||||||
path_str,
|
|
||||||
diag_info.ori_link,
|
|
||||||
sp,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"this link resolves to {}, which is not in the {} namespace",
|
"this link resolves to {}, which is not in the {} namespace",
|
||||||
|
@ -2224,8 +2238,7 @@ fn ambiguity_error(
|
||||||
}
|
}
|
||||||
|
|
||||||
for res in candidates {
|
for res in candidates {
|
||||||
let disambiguator = Disambiguator::from_res(res);
|
suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
|
||||||
suggest_disambiguator(disambiguator, diag, path_str, diag_info.ori_link, sp);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2233,14 +2246,14 @@ fn ambiguity_error(
|
||||||
/// In case of an ambiguity or mismatched disambiguator, suggest the correct
|
/// In case of an ambiguity or mismatched disambiguator, suggest the correct
|
||||||
/// disambiguator.
|
/// disambiguator.
|
||||||
fn suggest_disambiguator(
|
fn suggest_disambiguator(
|
||||||
disambiguator: Disambiguator,
|
res: Res,
|
||||||
diag: &mut DiagnosticBuilder<'_>,
|
diag: &mut DiagnosticBuilder<'_>,
|
||||||
path_str: &str,
|
path_str: &str,
|
||||||
ori_link: &str,
|
ori_link: &str,
|
||||||
sp: Option<rustc_span::Span>,
|
sp: Option<rustc_span::Span>,
|
||||||
) {
|
) {
|
||||||
let suggestion = disambiguator.suggestion();
|
let suggestion = res.disambiguator_suggestion();
|
||||||
let help = format!("to link to the {}, {}", disambiguator.descr(), suggestion.descr());
|
let help = format!("to link to the {}, {}", res.descr(), suggestion.descr());
|
||||||
|
|
||||||
if let Some(sp) = sp {
|
if let Some(sp) = sp {
|
||||||
let mut spans = suggestion.as_help_span(path_str, ori_link, sp);
|
let mut spans = suggestion.as_help_span(path_str, ori_link, sp);
|
||||||
|
|
|
@ -73,4 +73,9 @@ trait T {}
|
||||||
//~^ ERROR incompatible link kind for `f`
|
//~^ ERROR incompatible link kind for `f`
|
||||||
//~| NOTE this link resolved
|
//~| NOTE this link resolved
|
||||||
//~| HELP add parentheses
|
//~| HELP add parentheses
|
||||||
|
|
||||||
|
/// Link to [fn@std]
|
||||||
|
//~^ ERROR unresolved link to `std`
|
||||||
|
//~| NOTE this link resolves to the crate `std`
|
||||||
|
//~| HELP to link to the crate, prefix with `mod@`
|
||||||
pub fn f() {}
|
pub fn f() {}
|
||||||
|
|
|
@ -138,5 +138,16 @@ LL - /// Link to [const@f]
|
||||||
LL + /// Link to [f()]
|
LL + /// Link to [f()]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: unresolved link to `std`
|
||||||
|
--> $DIR/disambiguator-mismatch.rs:77:14
|
||||||
|
|
|
||||||
|
LL | /// Link to [fn@std]
|
||||||
|
| ^^^^^^ this link resolves to the crate `std`, which is not in the value namespace
|
||||||
|
|
|
||||||
|
help: to link to the crate, prefix with `mod@`
|
||||||
|
|
|
||||||
|
LL | /// Link to [mod@std]
|
||||||
|
| ~~~~
|
||||||
|
|
||||||
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,34 @@ extern {
|
||||||
pub type ExternType;
|
pub type ExternType;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternType {
|
pub trait T {
|
||||||
pub fn f(&self) {
|
fn test(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
pub trait G<N> {
|
||||||
|
fn g(&self, n: N) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExternType {
|
||||||
|
pub fn f(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl T for ExternType {
|
||||||
|
fn test(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl G<usize> for ExternType {
|
||||||
|
fn g(&self, n: usize) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has 'extern_type/foreigntype.ExternType.html'
|
// @has 'extern_type/foreigntype.ExternType.html'
|
||||||
// @has 'extern_type/fn.links_to_extern_type.html' \
|
// @has 'extern_type/fn.links_to_extern_type.html' \
|
||||||
// 'href="foreigntype.ExternType.html#method.f"'
|
// 'href="foreigntype.ExternType.html#method.f"'
|
||||||
|
// @has 'extern_type/fn.links_to_extern_type.html' \
|
||||||
|
// 'href="foreigntype.ExternType.html#method.test"'
|
||||||
|
// @has 'extern_type/fn.links_to_extern_type.html' \
|
||||||
|
// 'href="foreigntype.ExternType.html#method.g"'
|
||||||
/// See also [ExternType::f]
|
/// See also [ExternType::f]
|
||||||
|
/// See also [ExternType::test]
|
||||||
|
/// See also [ExternType::g]
|
||||||
pub fn links_to_extern_type() {}
|
pub fn links_to_extern_type() {}
|
||||||
|
|
20
src/test/rustdoc/intra-doc/generic-trait-impl.rs
Normal file
20
src/test/rustdoc/intra-doc/generic-trait-impl.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
|
|
||||||
|
// Test intra-doc links on trait implementations with generics
|
||||||
|
// regression test for issue #92662
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
pub trait Bar<T> {
|
||||||
|
fn bar(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Foo<U>(PhantomData<U>);
|
||||||
|
|
||||||
|
impl<T, U> Bar<T> for Foo<U> {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has generic_trait_impl/fn.main.html '//a[@href="struct.Foo.html#method.bar"]' 'Foo::bar'
|
||||||
|
/// link to [`Foo::bar`]
|
||||||
|
pub fn main() {}
|
|
@ -1,13 +1,15 @@
|
||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
|
#![allow(incomplete_features)] // inherent_associated_types
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(no_core)]
|
#![feature(no_core)]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
|
#![feature(inherent_associated_types)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
#[lang = "usize"]
|
#[lang = "usize"]
|
||||||
/// [Self::f]
|
/// [Self::f]
|
||||||
/// [Self::MAX]
|
/// [Self::MAX]
|
||||||
// @has intra_link_prim_self/primitive.usize.html
|
// @has prim_self/primitive.usize.html
|
||||||
// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
|
// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
|
||||||
// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
|
// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
|
||||||
impl usize {
|
impl usize {
|
||||||
|
@ -17,10 +19,9 @@ impl usize {
|
||||||
/// 10 and 2^32 are basically the same.
|
/// 10 and 2^32 are basically the same.
|
||||||
pub const MAX: usize = 10;
|
pub const MAX: usize = 10;
|
||||||
|
|
||||||
// FIXME(#8995) uncomment this when associated types in inherent impls are supported
|
// @has - '//a[@href="primitive.usize.html#associatedtype.ME"]' 'Self::ME'
|
||||||
// @ has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
|
/// [Self::ME]
|
||||||
// / [Self::ME]
|
pub type ME = usize;
|
||||||
//pub type ME = usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(primitive = "usize")]
|
#[doc(primitive = "usize")]
|
|
@ -1,80 +0,0 @@
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:13:13
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:4:9
|
|
||||||
|
|
|
||||||
LL | #![deny(rustc::ty_pass_by_reference)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:15:18
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:19:28
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:19:55
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:26:17
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:28:22
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:31:41
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:31:68
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:53:17
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:55:22
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:59:38
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:59:65
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
error: passing `TyCtxt<'tcx>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:18:15
|
|
||||||
|
|
|
||||||
LL | fn by_ref(&self) {}
|
|
||||||
| ^^^^^ help: try passing by value: `TyCtxt<'tcx>`
|
|
||||||
|
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:8:9
|
|
||||||
|
|
|
||||||
LL | #![deny(rustc::ty_pass_by_reference)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: passing `Ty<'tcx>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:31:21
|
|
||||||
|
|
|
||||||
LL | fn by_ref(self: &Ty<'tcx>) {}
|
|
||||||
| ^^^^^^^^^ help: try passing by value: `Ty<'tcx>`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// compile-flags: -Z unstable-options
|
// compile-flags: -Z unstable-options
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![deny(rustc::ty_pass_by_reference)]
|
#![deny(rustc::pass_by_value)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
@ -61,4 +62,57 @@ impl Foo {
|
||||||
//~^^ ERROR passing `TyCtxt<'_>` by reference
|
//~^^ ERROR passing `TyCtxt<'_>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
enum CustomEnum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CustomEnum {
|
||||||
|
fn test(
|
||||||
|
value: CustomEnum,
|
||||||
|
reference: &CustomEnum, //~ ERROR passing `CustomEnum` by reference
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct CustomStruct {
|
||||||
|
s: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
type CustomAlias<'a> = &'a CustomStruct; //~ ERROR passing `CustomStruct` by reference
|
||||||
|
|
||||||
|
impl CustomStruct {
|
||||||
|
fn test(
|
||||||
|
value: CustomStruct,
|
||||||
|
reference: &CustomStruct, //~ ERROR passing `CustomStruct` by reference
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_alias(
|
||||||
|
value: CustomAlias,
|
||||||
|
reference: &CustomAlias, //~ ERROR passing `CustomAlias<>` by reference
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct WithParameters<T, const N: usize, M = u32> {
|
||||||
|
slice: [T; N],
|
||||||
|
m: M,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1> {
|
||||||
|
fn test<'a>(
|
||||||
|
value: WithParameters<T, 1>,
|
||||||
|
reference: &'a WithParameters<T, 1>, //~ ERROR passing `WithParameters<T, 1>` by reference
|
||||||
|
reference_with_m: &WithParameters<T, 1, u32>, //~ ERROR passing `WithParameters<T, 1, u32>` by reference
|
||||||
|
) -> &'a WithParameters<T, 1> {
|
||||||
|
//~^ ERROR passing `WithParameters<T, 1>` by reference
|
||||||
|
reference as &WithParameters<_, 1> //~ ERROR passing `WithParameters<_, 1>` by reference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
128
src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr
Normal file
128
src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:14:13
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:5:9
|
||||||
|
|
|
||||||
|
LL | #![deny(rustc::pass_by_value)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:16:18
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:20:28
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:20:55
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:27:17
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:29:22
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:32:41
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:32:68
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:54:17
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:56:22
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:60:38
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:60:65
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `CustomEnum` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:74:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomEnum,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `CustomEnum`
|
||||||
|
|
||||||
|
error: passing `CustomStruct` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:85:24
|
||||||
|
|
|
||||||
|
LL | type CustomAlias<'a> = &'a CustomStruct;
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
||||||
|
|
||||||
|
error: passing `CustomStruct` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:90:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomStruct,
|
||||||
|
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
||||||
|
|
||||||
|
error: passing `CustomAlias<>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:96:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomAlias,
|
||||||
|
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:110:20
|
||||||
|
|
|
||||||
|
LL | reference: &'a WithParameters<T, 1>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1, u32>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:111:27
|
||||||
|
|
|
||||||
|
LL | reference_with_m: &WithParameters<T, 1, u32>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1, u32>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:112:10
|
||||||
|
|
|
||||||
|
LL | ) -> &'a WithParameters<T, 1> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<_, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:114:22
|
||||||
|
|
|
||||||
|
LL | reference as &WithParameters<_, 1>
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<_, 1>`
|
||||||
|
|
||||||
|
error: aborting due to 20 previous errors
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
// Considering that all other `internal-lints` are tested here
|
// Considering that all other `internal-lints` are tested here
|
||||||
// this seems like the cleaner solution though.
|
// this seems like the cleaner solution though.
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![deny(rustc::ty_pass_by_reference)]
|
#![deny(rustc::pass_by_value)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "TyCtxt"]
|
#[rustc_pass_by_value]
|
||||||
struct TyCtxt<'tcx> {
|
struct TyCtxt<'tcx> {
|
||||||
inner: &'tcx (),
|
inner: &'tcx (),
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
fn by_ref(&self) {} //~ ERROR passing `TyCtxt<'tcx>` by reference
|
fn by_ref(&self) {} //~ ERROR passing `TyCtxt<'tcx>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct TyS<'tcx> {
|
struct TyS<'tcx> {
|
||||||
inner: &'tcx (),
|
inner: &'tcx (),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "Ty"]
|
#[rustc_pass_by_value]
|
||||||
type Ty<'tcx> = &'tcx TyS<'tcx>;
|
type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||||
|
|
||||||
impl<'tcx> TyS<'tcx> {
|
impl<'tcx> TyS<'tcx> {
|
||||||
|
@ -31,4 +30,25 @@ impl<'tcx> TyS<'tcx> {
|
||||||
fn by_ref(self: &Ty<'tcx>) {} //~ ERROR passing `Ty<'tcx>` by reference
|
fn by_ref(self: &Ty<'tcx>) {} //~ ERROR passing `Ty<'tcx>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `Foo` by reference
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct WithParameters<T, const N: usize, M = u32> {
|
||||||
|
slice: [T; N],
|
||||||
|
m: M,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1> {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize>` by reference
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1, u8> {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize, u8>` by reference
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
|
@ -0,0 +1,38 @@
|
||||||
|
error: passing `TyCtxt<'tcx>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:18:15
|
||||||
|
|
|
||||||
|
LL | fn by_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `TyCtxt<'tcx>`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:8:9
|
||||||
|
|
|
||||||
|
LL | #![deny(rustc::pass_by_value)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: passing `Ty<'tcx>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:30:21
|
||||||
|
|
|
||||||
|
LL | fn by_ref(self: &Ty<'tcx>) {}
|
||||||
|
| ^^^^^^^^^ help: try passing by value: `Ty<'tcx>`
|
||||||
|
|
||||||
|
error: passing `Foo` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:37:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `Foo`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1_usize>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:47:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1_usize, u8>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:51:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize, u8>`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0311]: the parameter type `C` may not live long enough
|
||||||
|
--> $DIR/issue-92096.rs:20:33
|
||||||
|
|
|
||||||
|
LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
||||||
|
| |
|
||||||
|
| help: consider adding an explicit lifetime bound...: `C: 'a`
|
||||||
|
|
||||||
|
error[E0311]: the parameter type `C` may not live long enough
|
||||||
|
--> $DIR/issue-92096.rs:20:33
|
||||||
|
|
|
||||||
|
LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
||||||
|
| |
|
||||||
|
| help: consider adding an explicit lifetime bound...: `C: 'a`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
29
src/test/ui/generic-associated-types/issue-92096.rs
Normal file
29
src/test/ui/generic-associated-types/issue-92096.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// edition:2018
|
||||||
|
// [nll] check-pass
|
||||||
|
// revisions: migrate nll
|
||||||
|
// Explicitly testing nll with revision, so ignore compare-mode=nll
|
||||||
|
// ignore-compare-mode-nll
|
||||||
|
|
||||||
|
#![cfg_attr(nll, feature(nll))]
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
trait Client {
|
||||||
|
type Connecting<'a>: Future + Send
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn connect(&'_ self) -> Self::Connecting<'_>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
|
||||||
|
//[migrate]~^ ERROR the parameter
|
||||||
|
//[migrate]~| ERROR the parameter
|
||||||
|
where
|
||||||
|
C: Client + Send + Sync,
|
||||||
|
{
|
||||||
|
async move { c.connect().await }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
26
src/test/ui/generic-associated-types/issue-92280.rs
Normal file
26
src/test/ui/generic-associated-types/issue-92280.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
trait HasAssoc {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Iterate<S: HasAssoc> {
|
||||||
|
type Iter<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct KeySegment_Broken<T> {
|
||||||
|
key: T,
|
||||||
|
}
|
||||||
|
impl<S: HasAssoc> Iterate<S> for KeySegment_Broken<S::Assoc> {
|
||||||
|
type Iter<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -589,7 +589,7 @@ fn test_item() {
|
||||||
stringify_item!(
|
stringify_item!(
|
||||||
pub trait Trait<T> = Sized where T: 'a;
|
pub trait Trait<T> = Sized where T: 'a;
|
||||||
),
|
),
|
||||||
"", // FIXME
|
"pub trait Trait<T> = Sized where T: 'a;",
|
||||||
);
|
);
|
||||||
|
|
||||||
// ItemKind::Impl
|
// ItemKind::Impl
|
||||||
|
|
|
@ -117,9 +117,9 @@ static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
|
||||||
|
|
||||||
pub fn cast_then_try() -> Result<u64,u64> {
|
pub fn cast_then_try() -> Result<u64,u64> {
|
||||||
Err(0u64) as Result<u64,u64>?;
|
Err(0u64) as Result<u64,u64>?;
|
||||||
//~^ ERROR: casts cannot be followed by ?
|
//~^ ERROR: casts cannot be followed by `?`
|
||||||
Err(0u64): Result<u64,u64>?;
|
Err(0u64): Result<u64,u64>?;
|
||||||
//~^ ERROR: casts cannot be followed by ?
|
//~^ ERROR: casts cannot be followed by `?`
|
||||||
Ok(1)
|
Ok(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,7 @@ help: try surrounding the expression in parentheses
|
||||||
LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]);
|
LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]);
|
||||||
| + +
|
| + +
|
||||||
|
|
||||||
error: casts cannot be followed by ?
|
error: casts cannot be followed by `?`
|
||||||
--> $DIR/issue-35813-postfix-after-cast.rs:119:5
|
--> $DIR/issue-35813-postfix-after-cast.rs:119:5
|
||||||
|
|
|
|
||||||
LL | Err(0u64) as Result<u64,u64>?;
|
LL | Err(0u64) as Result<u64,u64>?;
|
||||||
|
@ -276,7 +276,7 @@ help: try surrounding the expression in parentheses
|
||||||
LL | (Err(0u64) as Result<u64,u64>)?;
|
LL | (Err(0u64) as Result<u64,u64>)?;
|
||||||
| + +
|
| + +
|
||||||
|
|
||||||
error: casts cannot be followed by ?
|
error: casts cannot be followed by `?`
|
||||||
--> $DIR/issue-35813-postfix-after-cast.rs:121:5
|
--> $DIR/issue-35813-postfix-after-cast.rs:121:5
|
||||||
|
|
|
|
||||||
LL | Err(0u64): Result<u64,u64>?;
|
LL | Err(0u64): Result<u64,u64>?;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
fn f(t:for<>t?)
|
fn f(t:for<>t?)
|
||||||
//~^ ERROR: expected parameter name
|
//~^ ERROR: expected one of
|
||||||
//~| ERROR: expected one of
|
//~| ERROR: invalid `?` in type
|
||||||
//~| ERROR: expected one of
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
error: expected parameter name, found `?`
|
error: invalid `?` in type
|
||||||
--> $DIR/issue-84148-1.rs:1:14
|
--> $DIR/issue-84148-1.rs:1:14
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?)
|
LL | fn f(t:for<>t?)
|
||||||
| ^ expected parameter name
|
| ^ `?` is only allowed on expressions, not types
|
||||||
|
|
||||||
error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
|
|
||||||
--> $DIR/issue-84148-1.rs:1:14
|
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?)
|
help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
|
||||||
| ^
|
|
|
||||||
| |
|
LL | fn f(t:Option<for<>t>)
|
||||||
| expected one of `(`, `)`, `+`, `,`, `::`, or `<`
|
| +++++++ ~
|
||||||
| help: missing `,`
|
|
||||||
|
|
||||||
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
||||||
--> $DIR/issue-84148-1.rs:1:15
|
--> $DIR/issue-84148-1.rs:1:15
|
||||||
|
@ -19,5 +15,5 @@ error: expected one of `->`, `where`, or `{`, found `<eof>`
|
||||||
LL | fn f(t:for<>t?)
|
LL | fn f(t:for<>t?)
|
||||||
| ^ expected one of `->`, `where`, or `{`
|
| ^ expected one of `->`, `where`, or `{`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// error-pattern: this file contains an unclosed delimiter
|
// error-pattern: this file contains an unclosed delimiter
|
||||||
// error-pattern: expected parameter name
|
// error-pattern: invalid `?` in type
|
||||||
// error-pattern: expected one of
|
|
||||||
fn f(t:for<>t?
|
fn f(t:for<>t?
|
||||||
|
|
|
@ -1,31 +1,27 @@
|
||||||
error: this file contains an unclosed delimiter
|
error: this file contains an unclosed delimiter
|
||||||
--> $DIR/issue-84148-2.rs:4:16
|
--> $DIR/issue-84148-2.rs:3:16
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?
|
LL | fn f(t:for<>t?
|
||||||
| - ^
|
| - ^
|
||||||
| |
|
| |
|
||||||
| unclosed delimiter
|
| unclosed delimiter
|
||||||
|
|
||||||
error: expected parameter name, found `?`
|
error: invalid `?` in type
|
||||||
--> $DIR/issue-84148-2.rs:4:14
|
--> $DIR/issue-84148-2.rs:3:14
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?
|
LL | fn f(t:for<>t?
|
||||||
| ^ expected parameter name
|
| ^ `?` is only allowed on expressions, not types
|
||||||
|
|
||||||
error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
|
|
||||||
--> $DIR/issue-84148-2.rs:4:14
|
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?
|
help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
|
||||||
| ^
|
|
|
||||||
| |
|
LL | fn f(t:Option<for<>t>
|
||||||
| expected one of `(`, `)`, `+`, `,`, `::`, or `<`
|
| +++++++ ~
|
||||||
| help: missing `,`
|
|
||||||
|
|
||||||
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
error: expected one of `->`, `where`, or `{`, found `<eof>`
|
||||||
--> $DIR/issue-84148-2.rs:4:16
|
--> $DIR/issue-84148-2.rs:3:16
|
||||||
|
|
|
|
||||||
LL | fn f(t:for<>t?
|
LL | fn f(t:for<>t?
|
||||||
| ^ expected one of `->`, `where`, or `{`
|
| ^ expected one of `->`, `where`, or `{`
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
10
src/test/ui/parser/trailing-question-in-type.fixed
Normal file
10
src/test/ui/parser/trailing-question-in-type.fixed
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn foo() -> Option<i32> { //~ ERROR invalid `?` in type
|
||||||
|
let x: Option<i32> = Some(1); //~ ERROR invalid `?` in type
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Option<i32> = foo();
|
||||||
|
}
|
10
src/test/ui/parser/trailing-question-in-type.rs
Normal file
10
src/test/ui/parser/trailing-question-in-type.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
fn foo() -> i32? { //~ ERROR invalid `?` in type
|
||||||
|
let x: i32? = Some(1); //~ ERROR invalid `?` in type
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Option<i32> = foo();
|
||||||
|
}
|
24
src/test/ui/parser/trailing-question-in-type.stderr
Normal file
24
src/test/ui/parser/trailing-question-in-type.stderr
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
error: invalid `?` in type
|
||||||
|
--> $DIR/trailing-question-in-type.rs:3:16
|
||||||
|
|
|
||||||
|
LL | fn foo() -> i32? {
|
||||||
|
| ^ `?` is only allowed on expressions, not types
|
||||||
|
|
|
||||||
|
help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
|
||||||
|
|
|
||||||
|
LL | fn foo() -> Option<i32> {
|
||||||
|
| +++++++ ~
|
||||||
|
|
||||||
|
error: invalid `?` in type
|
||||||
|
--> $DIR/trailing-question-in-type.rs:4:15
|
||||||
|
|
|
||||||
|
LL | let x: i32? = Some(1);
|
||||||
|
| ^ `?` is only allowed on expressions, not types
|
||||||
|
|
|
||||||
|
help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
|
||||||
|
|
|
||||||
|
LL | let x: Option<i32> = Some(1);
|
||||||
|
| +++++++ ~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue