diff options
91 files changed, 2697 insertions, 459 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 068b255e9f2..58ce73047bc 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -150,6 +150,8 @@ pub fn print_crate<'a>( /// and also addresses some specific regressions described in #63896 and #73345. fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { if let TokenTree::Token(token, _) = prev { + // No space after these tokens, e.g. `x.y`, `$e` + // (The carets point to `prev`.) ^ ^ if matches!(token.kind, token::Dot | token::Dollar) { return false; } @@ -158,10 +160,19 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { } } match tt { + // No space before these tokens, e.g. `foo,`, `println!`, `x.y` + // (The carets point to `token`.) ^ ^ ^ + // + // FIXME: having `Not` here works well for macro invocations like + // `println!()`, but is bad when `!` means "logical not" or "the never + // type", where the lack of space causes ugliness like this: + // `Fn() ->!`, `x =! y`, `if! x { f(); }`. TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot), + // No space before parentheses if preceded by these tokens, e.g. `foo(...)` TokenTree::Delimited(_, Delimiter::Parenthesis, _) => { !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _)) } + // No space before brackets if preceded by these tokens, e.g. `#[...]` TokenTree::Delimited(_, Delimiter::Bracket, _) => { !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _)) } diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index d257145373f..becfa535a59 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -30,7 +30,7 @@ pub use super::{ /// will be retrieved. #[derive(Debug, Copy, Clone)] pub enum ConsumerOptions { - /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet) + /// Retrieve the [`Body`] along with the [`BorrowSet`] /// and [`RegionInferenceContext`]. If you would like the body only, use /// [`TyCtxt::mir_promoted`]. /// diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 4c9094bf1f5..b6c01545f30 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -128,7 +128,10 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attr // The function name varies on platforms. // See test/CodeGen/mcount.c in clang. - let mcount_name = cx.sess().target.mcount.as_ref(); + let mcount_name = match &cx.sess().target.llvm_mcount_intrinsic { + Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(), + None => cx.sess().target.mcount.as_ref(), + }; attrs.push(llvm::CreateAttrStringValue( cx.llcx, diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 0be84c9fa83..4c854740753 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -16,6 +16,7 @@ use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; use rustc_session::Session; +use rustc_span::sym; use rustc_target::abi::Endian; use rustc_target::spec::{ef_avr_arch, RelocModel, Target}; @@ -272,35 +273,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static Architecture::Riscv32 | Architecture::Riscv64 => { // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc let mut e_flags: u32 = 0x0; - let features = &sess.target.options.features; + // Check if compressed is enabled - if features.contains("+c") { + // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature. + if sess.unstable_target_features.contains(&sym::c) { e_flags |= elf::EF_RISCV_RVC; } - // Select the appropriate floating-point ABI - if features.contains("+d") { - e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE; - } else if features.contains("+f") { - e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE; - } else { - e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT; + // Set the appropriate flag based on ABI + // This needs to match LLVM `RISCVELFStreamer.cpp` + match &*sess.target.llvm_abiname { + "" | "ilp32" | "lp64" => (), + "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE, + "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE, + "ilp32e" => e_flags |= elf::EF_RISCV_RVE, + _ => bug!("unknown RISC-V ABI name"), } + e_flags } Architecture::LoongArch64 => { // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1; - let features = &sess.target.options.features; - // Select the appropriate floating-point ABI - if features.contains("+d") { - e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT; - } else if features.contains("+f") { - e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT; - } else { - e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT; + // Set the appropriate flag based on ABI + // This needs to match LLVM `LoongArchELFStreamer.cpp` + match &*sess.target.llvm_abiname { + "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT, + "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT, + "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT, + _ => bug!("unknown RISC-V ABI name"), } + e_flags } Architecture::Avr => { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 032f4be6c99..b740b79d162 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -427,52 +427,41 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn find_mir_or_eval_fn( ecx: &mut InterpCx<'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, + orig_instance: ty::Instance<'tcx>, _abi: CallAbi, args: &[FnArg<'tcx>], dest: &PlaceTy<'tcx>, ret: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { - debug!("find_mir_or_eval_fn: {:?}", instance); + debug!("find_mir_or_eval_fn: {:?}", orig_instance); + + // Replace some functions. + let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else { + // Call has already been handled. + return Ok(None); + }; // Only check non-glue functions if let ty::InstanceDef::Item(def) = instance.def { // Execution might have wandered off into other crates, so we cannot do a stability- - // sensitive check here. But we can at least rule out functions that are not const - // at all. - if !ecx.tcx.is_const_fn_raw(def) { - // allow calling functions inside a trait marked with #[const_trait]. - if !ecx.tcx.is_const_default_method(def) { - // We certainly do *not* want to actually call the fn - // though, so be sure we return here. - throw_unsup_format!("calling non-const function `{}`", instance) - } - } - - let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else { - return Ok(None); - }; - - if new_instance != instance { - // We call another const fn instead. - // However, we return the *original* instance to make backtraces work out - // (and we hope this does not confuse the FnAbi checks too much). - return Ok(Self::find_mir_or_eval_fn( - ecx, - new_instance, - _abi, - args, - dest, - ret, - _unwind, - )? - .map(|(body, _instance)| (body, instance))); + // sensitive check here. But we can at least rule out functions that are not const at + // all. That said, we have to allow calling functions inside a trait marked with + // #[const_trait]. These *are* const-checked! + // FIXME: why does `is_const_fn_raw` not classify them as const? + if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def)) + || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check) + { + // We certainly do *not* want to actually call the fn + // though, so be sure we return here. + throw_unsup_format!("calling non-const function `{}`", instance) } } // This is a const fn. Call it. - Ok(Some((ecx.load_mir(instance.def, None)?, instance))) + // In case of replacement, we return the *original* instance to make backtraces work out + // (and we hope this does not confuse the FnAbi checks too much). + Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance))) } fn call_intrinsic( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7d660d2dbaa..34518b53759 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -452,11 +452,11 @@ struct HandlerInner { /// have been converted. check_unstable_expect_diagnostics: bool, - /// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of + /// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of /// the lint level. [`LintExpectationId`]s created early during the compilation /// (before `HirId`s have been defined) are not stable and can therefore not be /// stored on disk. This buffer stores these diagnostics until the ID has been - /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the + /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the /// submitted for storage and added to the list of fulfilled expectations. unstable_expect_diagnostics: Vec<Diagnostic>, diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 05c0cd952b8..7e85beaadcb 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -81,7 +81,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorGuaranteed; use rustc_lint_defs::pluralize; -use rustc_parse::parser::{NtOrTt, Parser}; +use rustc_parse::parser::{ParseNtResult, Parser}; use rustc_span::symbol::Ident; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -692,8 +692,8 @@ impl TtParser { Ok(nt) => nt, }; let m = match nt { - NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), - NtOrTt::Tt(tt) => MatchedTokenTree(tt), + ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), + ParseNtResult::Tt(tt) => MatchedTokenTree(tt), }; mp.push_match(next_metavar, seq_depth, m); mp.idx += 1; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index ce8b4621720..a5959d68fbc 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1328,7 +1328,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { _ => IsInFollow::No(TOKENS), } } - NonterminalKind::PatWithOr { .. } => { + NonterminalKind::PatWithOr => { const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index b6382dcb894..7c37aadc67a 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -93,7 +93,17 @@ fn parse_count<'sess>( span: Span, ) -> PResult<'sess, MetaVarExpr> { let ident = parse_ident(iter, sess, span)?; - let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None }; + let depth = if try_eat_comma(iter) { + if iter.look_ahead(0).is_none() { + return Err(sess.span_diagnostic.struct_span_err( + span, + "`count` followed by a comma must have an associated index indicating its depth", + )); + } + Some(parse_depth(iter, sess, span)?) + } else { + None + }; Ok(MetaVarExpr::Count(ident, depth)) } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index a5f83b88f7e..15e7ab3fe3e 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -220,16 +220,15 @@ pub(super) fn transcribe<'a>( MatchedTokenTree(tt) => { // `tt`s are emitted into the output stream directly as "raw tokens", // without wrapping them into groups. - let token = tt.clone(); - result.push(token); + result.push(tt.clone()); } MatchedNonterminal(nt) => { // Other variables are emitted into the output stream as groups with // `Delimiter::Invisible` to maintain parsing priorities. // `Interpolated` is currently used for such groups in rustc parser. marker.visit_span(&mut sp); - let token = TokenTree::token_alone(token::Interpolated(nt.clone()), sp); - result.push(token); + result + .push(TokenTree::token_alone(token::Interpolated(nt.clone()), sp)); } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 953ea1bf523..f5708f933d5 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -352,6 +352,8 @@ declare_features! ( (active, c_variadic, "1.34.0", Some(44930), None), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. (active, cfg_overflow_checks, "1.71.0", Some(111466), None), + /// Provides the relocation model information as cfg entry + (active, cfg_relocation_model, "CURRENT_RUSTC_VERSION", Some(114929), None), /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (active, cfg_sanitize, "1.41.0", Some(39699), None), /// Allows `cfg(target_abi = "...")`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a183cfd8776..2f7cff3ce5c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -35,6 +35,7 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), + (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 5bc0e2ee86c..31a03fabe4f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: expr_ty, mutbl }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() && expr_mutbl == Mutability::Not && mutbl == Mutability::Mut && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, expr_reg, TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg_mutref = true; } @@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { if !sugg_mutref && sugg == None && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() && fcx - .try_coerce( - self.expr, + .can_coerce( Ty::new_ref(fcx.tcx, fcx.tcx.lifetimes.re_erased, TypeAndMut { ty: self.expr_ty, mutbl }, ), self.cast_ty, - AllowTwoPhase::No, - None, ) - .is_ok() { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } @@ -760,7 +744,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ty::FnDef(..) => { // Attempt a coercion to a fn pointer type. let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx)); - let res = fcx.try_coerce( + let res = fcx.coerce( self.expr, self.expr_ty, Ty::new_fn_ptr(fcx.tcx, f), @@ -860,7 +844,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { (_, DynStar) => { if fcx.tcx.features().dyn_star { - bug!("should be handled by `try_coerce`") + bug!("should be handled by `coerce`") } else { Err(CastError::IllegalCast) } @@ -956,7 +940,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Coerce to a raw pointer so that we generate AddressOf in MIR. let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr); - fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) + fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) .unwrap_or_else(|_| { bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", @@ -992,7 +976,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> { - match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) { + match fcx.coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) { Ok(_) => Ok(()), Err(err) => Err(err), } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 726914a995b..fca675ea9d8 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// adjusted type of the expression, if successful. /// Adjustments are only recorded if the coercion succeeded. /// The expressions *must not* have any preexisting adjustments. - pub fn try_coerce( + pub fn coerce( &self, expr: &hir::Expr<'_>, expr_ty: Ty<'tcx>, @@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) } - /// Same as `try_coerce()`, but without side-effects. + /// Same as `coerce()`, but without side-effects. /// /// Returns false if the coercion creates any obligations that result in /// errors. @@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // Special-case the first expression we are coercing. // To be honest, I'm not entirely sure why we do this. // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why - fcx.try_coerce( + fcx.coerce( expression, expression_ty, self.expected_ty, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6aeabc1bebb..2c16f21b491 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) { let expected = self.resolve_vars_with_obligations(expected); - let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) { + let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) { Ok(ty) => return (ty, None), Err(e) => e, }; @@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; }; let arg_ty = arg_ty.fold_with(&mut fudger); - let _ = self.try_coerce( + let _ = self.coerce( arg_expr, arg_ty, *expected_arg_ty, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 004c8affcf0..4def7867384 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -260,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // fulfillment error to be more accurate. let coerced_ty = self.resolve_vars_with_obligations(coerced_ty); - let coerce_error = self - .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None) - .err(); + let coerce_error = + self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err(); if coerce_error.is_some() { return Compatibility::Incompatible(coerce_error); diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs index 5b19a4c525f..3f1dca5b1de 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs @@ -14,6 +14,7 @@ use rustc_span::symbol::kw::{Empty, Underscore}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; +use std::fmt::Write; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(super) fn lint_dot_call_from_2018( @@ -143,16 +144,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp); if precise { - let args = args - .iter() - .map(|arg| { - let span = arg.span.find_ancestor_inside(sp).unwrap_or_default(); - format!( - ", {}", - self.sess().source_map().span_to_snippet(span).unwrap() - ) - }) - .collect::<String>(); + let args = args.iter().fold(String::new(), |mut string, arg| { + let span = arg.span.find_ancestor_inside(sp).unwrap_or_default(); + write!( + string, + ", {}", + self.sess().source_map().span_to_snippet(span).unwrap() + ) + .unwrap(); + string + }); lint.span_suggestion( sp, diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index f1e7b8eb6c7..ba75517d7a6 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -59,14 +59,14 @@ fn decodable_body( }) .collect(); let message = format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", + "invalid enum variant tag while decoding `{}`, expected 0..{}, actual {{}}", ty_name, variants.len() ); quote! { match ::rustc_serialize::Decoder::read_usize(__decoder) { #match_inner - _ => panic!(#message), + n => panic!(#message, n), } } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index e8fd469e1fb..0da8fe9cca7 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -164,18 +164,15 @@ pub fn provide(providers: &mut Providers) { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; providers.def_span = |tcx, def_id| { - let def_id = def_id; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP) }; providers.def_ident_span = |tcx, def_id| { - let def_id = def_id; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.hir().opt_ident_span(hir_id) }; - providers.fn_arg_names = |tcx, id| { + providers.fn_arg_names = |tcx, def_id| { let hir = tcx.hir(); - let def_id = id; let hir_id = hir.local_def_id_to_hir_id(def_id); if let Some(body_id) = hir.maybe_body_owned_by(def_id) { tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) @@ -190,7 +187,7 @@ pub fn provide(providers: &mut Providers) { { idents } else { - span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id); + span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id); } }; providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index e71482326da..5db9b775a0f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,6 +1,7 @@ //! Diagnostics related methods for `Ty`. use std::borrow::Cow; +use std::fmt::Write; use std::ops::ControlFlow; use crate::ty::{ @@ -335,10 +336,10 @@ pub fn suggest_constraining_type_params<'a>( // - insert: `, X: Bar` suggestions.push(( generics.tail_span_for_predicate_suggestion(), - constraints - .iter() - .map(|&(constraint, _)| format!(", {param_name}: {constraint}")) - .collect::<String>(), + constraints.iter().fold(String::new(), |mut string, &(constraint, _)| { + write!(string, ", {param_name}: {constraint}").unwrap(); + string + }), SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name }, )); continue; diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index d2c0c4ba069..083f1f8aef6 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -199,9 +199,9 @@ impl DebugOptions { fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool { if let Some(val) = some_strval { - if vec!["yes", "y", "on", "true"].contains(&val) { + if ["yes", "y", "on", "true"].contains(&val) { true - } else if vec!["no", "n", "off", "false"].contains(&val) { + } else if ["no", "n", "off", "false"].contains(&val) { false } else { bug!( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e409c7c6781..e308e5b3420 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -193,13 +193,7 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { - // Adjust the span for interpolated LHS to point to the `$lhs` token - // and not to what it refers to. - let lhs_span = match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_token.span, - _ => lhs.span, - }; - + let lhs_span = self.interpolated_or_expr_span(&lhs); let cur_op_span = self.token.span; let restrictions = if op.node.is_assign_like() { self.restrictions & Restrictions::NO_STRUCT_LITERAL @@ -626,8 +620,8 @@ impl<'a> Parser<'a> { fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> { self.bump(); - let expr = self.parse_expr_prefix(None); - let (span, expr) = self.interpolated_or_expr_span(expr)?; + let expr = self.parse_expr_prefix(None)?; + let span = self.interpolated_or_expr_span(&expr); Ok((lo.to(span), expr)) } @@ -702,20 +696,12 @@ impl<'a> Parser<'a> { self.parse_expr_unary(lo, UnOp::Not) } - /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. - fn interpolated_or_expr_span( - &self, - expr: PResult<'a, P<Expr>>, - ) -> PResult<'a, (Span, P<Expr>)> { - expr.map(|e| { - ( - match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_token.span, - _ => e.span, - }, - e, - ) - }) + /// Returns the span of expr if it was not interpolated, or the span of the interpolated token. + fn interpolated_or_expr_span(&self, expr: &Expr) -> Span { + match self.prev_token.kind { + TokenKind::Interpolated(..) => self.prev_token.span, + _ => expr.span, + } } fn parse_assoc_op_cast( @@ -898,8 +884,8 @@ impl<'a> Parser<'a> { self.parse_expr_prefix_range(None) } else { self.parse_expr_prefix(None) - }; - let (hi, expr) = self.interpolated_or_expr_span(expr)?; + }?; + let hi = self.interpolated_or_expr_span(&expr); let span = lo.to(hi); if let Some(lt) = lifetime { self.error_remove_borrow_lifetime(span, lt.ident.span); @@ -930,8 +916,8 @@ impl<'a> Parser<'a> { fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> { let attrs = self.parse_or_use_outer_attributes(attrs)?; self.collect_tokens_for_expr(attrs, |this, attrs| { - let base = this.parse_expr_bottom(); - let (span, base) = this.interpolated_or_expr_span(base)?; + let base = this.parse_expr_bottom()?; + let span = this.interpolated_or_expr_span(&base); this.parse_expr_dot_or_call_with(base, span, attrs) }) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ce4d4a60551..77c59bb3881 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1052,33 +1052,48 @@ impl<'a> Parser<'a> { } /// Look-ahead `dist` tokens of `self.token` and get access to that token there. - /// When `dist == 0` then the current token is looked at. + /// When `dist == 0` then the current token is looked at. `Eof` will be + /// returned if the look-ahead is any distance past the end of the tokens. pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R { if dist == 0 { return looker(&self.token); } - let tree_cursor = &self.token_cursor.tree_cursor; if let Some(&(_, delim, span)) = self.token_cursor.stack.last() && delim != Delimiter::Invisible { + // We are not in the outermost token stream, and the token stream + // we are in has non-skipped delimiters. Look for skipped + // delimiters in the lookahead range. + let tree_cursor = &self.token_cursor.tree_cursor; let all_normal = (0..dist).all(|i| { let token = tree_cursor.look_ahead(i); !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _))) }); if all_normal { + // There were no skipped delimiters. Do lookahead by plain indexing. return match tree_cursor.look_ahead(dist - 1) { - Some(tree) => match tree { - TokenTree::Token(token, _) => looker(token), - TokenTree::Delimited(dspan, delim, _) => { - looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + Some(tree) => { + // Indexing stayed within the current token stream. + match tree { + TokenTree::Token(token, _) => looker(token), + TokenTree::Delimited(dspan, delim, _) => { + looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + } } - }, - None => looker(&Token::new(token::CloseDelim(delim), span.close)), + } + None => { + // Indexing went past the end of the current token + // stream. Use the close delimiter, no matter how far + // ahead `dist` went. + looker(&Token::new(token::CloseDelim(delim), span.close)) + } }; } } + // We are in a more complex case. Just clone the token cursor and use + // `next`, skipping delimiters as necessary. Slow but simple. let mut cursor = self.token_cursor.clone(); let mut i = 0; let mut token = Token::dummy(); @@ -1476,7 +1491,7 @@ pub enum FlatToken { } #[derive(Debug)] -pub enum NtOrTt { +pub enum ParseNtResult { Nt(Nonterminal), Tt(TokenTree), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index f5681532b3a..ff059a7e865 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,5 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, NonterminalKind, Token}; +use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_errors::IntoDiagnostic; @@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Ident}; use crate::errors::UnexpectedNonterminal; use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle}; +use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle}; impl<'a> Parser<'a> { /// Checks whether a non-terminal may begin with a particular token. @@ -20,10 +20,21 @@ impl<'a> Parser<'a> { pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { - !matches!( - *nt, - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) - ) + match nt { + NtStmt(_) + | NtPat(_) + | NtExpr(_) + | NtTy(_) + | NtIdent(..) + | NtLiteral(_) // `true`, `false` + | NtMeta(_) + | NtPath(_) => true, + + NtItem(_) + | NtBlock(_) + | NtVis(_) + | NtLifetime(_) => false, + } } match kind { @@ -44,27 +55,19 @@ impl<'a> Parser<'a> { }, NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, - token::Interpolated(nt) => !matches!( - **nt, - token::NtItem(_) - | token::NtPat(_) - | token::NtTy(_) - | token::NtIdent(..) - | token::NtMeta(_) - | token::NtPath(_) - | token::NtVis(_) - ), + token::Interpolated(nt) => match **nt { + NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true, + NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_) + | NtVis(_) => false, + }, _ => false, }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::ModSep | token::Ident(..) => true, - token::Interpolated(nt) => match **nt { - token::NtPath(_) | token::NtMeta(_) => true, - _ => may_be_ident(&nt), - }, + token::Interpolated(nt) => may_be_ident(nt), _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { match &token.kind { token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern @@ -79,7 +82,7 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), + token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), token::Interpolated(nt) => may_be_ident(nt), _ => false, } @@ -87,7 +90,7 @@ impl<'a> Parser<'a> { NonterminalKind::Lifetime => match &token.kind { token::Lifetime(_) => true, token::Interpolated(nt) => { - matches!(**nt, token::NtLifetime(_)) + matches!(**nt, NtLifetime(_)) } _ => false, }, @@ -100,18 +103,16 @@ impl<'a> Parser<'a> { /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call /// site. #[inline] - pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> { - // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`) - // needs to have them force-captured here. + pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> { // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, // we always capture tokens for any `Nonterminal` which needs them. let mut nt = match kind { // Note that TT is treated differently to all the others. - NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())), + NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { - Some(item) => token::NtItem(item), + Some(item) => NtItem(item), None => { return Err(UnexpectedNonterminal::Item(self.token.span) .into_diagnostic(&self.sess.span_diagnostic)); @@ -120,19 +121,19 @@ impl<'a> Parser<'a> { NonterminalKind::Block => { // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`), // the ':block' matcher does not support them - token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) + NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(s) => token::NtStmt(P(s)), + Some(s) => NtStmt(P(s)), None => { return Err(UnexpectedNonterminal::Statement(self.token.span) .into_diagnostic(&self.sess.span_diagnostic)); } }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { - token::NtPat(self.collect_tokens_no_attrs(|this| match kind { + NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { + NtPat(self.collect_tokens_no_attrs(|this| match kind { NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None), - NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt( + NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, @@ -142,16 +143,16 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?), NonterminalKind::Literal => { // The `:literal` matcher does not support attributes - token::NtLiteral( + NtLiteral( self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, ) } - NonterminalKind::Ty => token::NtTy( - self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?, + NonterminalKind::Ty => NtTy( + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, ), // this could be handled like a token, since it is one @@ -159,7 +160,7 @@ impl<'a> Parser<'a> { if let Some((ident, is_raw)) = get_macro_ident(&self.token) => { self.bump(); - token::NtIdent(ident, is_raw) + NtIdent(ident, is_raw) } NonterminalKind::Ident => { return Err(UnexpectedNonterminal::Ident { @@ -167,16 +168,16 @@ impl<'a> Parser<'a> { token: self.token.clone(), }.into_diagnostic(&self.sess.span_diagnostic)); } - NonterminalKind::Path => token::NtPath( + NonterminalKind::Path => NtPath( P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?), ), - NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), - NonterminalKind::Vis => token::NtVis( + NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)), + NonterminalKind::Vis => NtVis( P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?), ), NonterminalKind::Lifetime => { if self.check_lifetime() { - token::NtLifetime(self.expect_lifetime().ident) + NtLifetime(self.expect_lifetime().ident) } else { return Err(UnexpectedNonterminal::Lifetime { span: self.token.span, @@ -196,7 +197,7 @@ impl<'a> Parser<'a> { ); } - Ok(NtOrTt::Nt(nt)) + Ok(ParseNtResult::Nt(nt)) } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 27b1e9c0f11..2d888efb1f3 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -180,7 +180,7 @@ impl<'a> Parser<'a> { ) } - pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> { + pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> { self.parse_ty_common( AllowPlus::Yes, AllowCVariadic::No, diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 0463ee2914b..a7a8af864ac 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -27,7 +27,6 @@ pub fn test_layout(tcx: TyCtxt<'_>) { } fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { - let tcx = tcx; let param_env = tcx.param_env(item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); match tcx.layout_of(param_env.and(ty)) { diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 0c0b8b6d094..20e996eaec4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1105,7 +1105,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } // Then do a second pass for inputs - let mut succ = succ; for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } => { diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index d433391f272..ba7417b6dda 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -1,4 +1,4 @@ -use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag}; +use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag}; use rustc_ast as ast; use rustc_ast::util::comments::beautify_doc_string; use rustc_data_structures::fx::FxHashMap; @@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap(); - Parser::new_with_broken_link_callback( + parse_links(&doc) +} + +/// Similiar version of `markdown_links` from rustdoc. +/// This will collect destination links and display text if exists. +fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> { + let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut event_iter = Parser::new_with_broken_link_callback( &doc, main_body_opts(), - Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))), + Some(&mut broken_link_callback), ) - .filter_map(|event| match event { - Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { - Some(preprocess_link(&dest)) + .into_iter(); + let mut links = Vec::new(); + + while let Some(event) = event_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { + if matches!( + link_type, + LinkType::Inline + | LinkType::ReferenceUnknown + | LinkType::Reference + | LinkType::Shortcut + | LinkType::ShortcutUnknown + ) { + if let Some(display_text) = collect_link_data(&mut event_iter) { + links.push(display_text); + } + } + + links.push(preprocess_link(&dest)); + } + _ => {} + } + } + + links +} + +/// Collects additional data of link. +fn collect_link_data<'input, 'callback>( + event_iter: &mut Parser<'input, 'callback>, +) -> Option<Box<str>> { + let mut display_text: Option<String> = None; + let mut append_text = |text: CowStr<'_>| { + if let Some(display_text) = &mut display_text { + display_text.push_str(&text); + } else { + display_text = Some(text.to_string()); + } + }; + + while let Some(event) = event_iter.next() { + match event { + Event::Text(text) => { + append_text(text); + } + Event::Code(code) => { + append_text(code); + } + Event::End(_) => { + break; + } + _ => {} } - _ => None, - }) - .collect() + } + + display_text.map(String::into_boxed_str) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 28ae88424ab..f00472f181d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,7 +12,7 @@ use crate::{EarlyErrorHandler, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_target::abi::Align; -use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; +use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; use crate::parse::{CrateCheckConfig, CrateConfig}; @@ -1193,6 +1193,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { let os = &sess.target.os; let env = &sess.target.env; let abi = &sess.target.abi; + let relocation_model = sess.target.relocation_model.desc_symbol(); let vendor = &sess.target.vendor; let min_atomic_width = sess.target.min_atomic_width(); let max_atomic_width = sess.target.max_atomic_width(); @@ -1218,6 +1219,9 @@ fn default_configuration(sess: &Session) -> CrateConfig { ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_abi, Some(Symbol::intern(abi)))); + if sess.is_nightly_build() { + ret.insert((sym::relocation_model, Some(relocation_model))); + } ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); if sess.target.has_thread_local { ret.insert((sym::target_thread_local, None)); @@ -1415,6 +1419,8 @@ impl CrateCheckConfig { .into_iter() .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap())); + let relocation_model_values = RelocModel::all(); + // Unknown possible values: // - `feature` // - `target_feature` @@ -1453,6 +1459,10 @@ impl CrateCheckConfig { .entry(sym::target_has_atomic_equal_alignment) .or_insert_with(no_values) .extend(atomic_values); + self.expecteds + .entry(sym::relocation_model) + .or_insert_with(empty_values) + .extend(relocation_model_values); // Target specific values { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index edbf51e9b33..28a2dfebcfe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -445,6 +445,7 @@ symbols! { bridge, bswap, builtin_syntax, + c, c_str, c_str_literals, c_unwind, @@ -468,6 +469,7 @@ symbols! { cfg_hide, cfg_overflow_checks, cfg_panic, + cfg_relocation_model, cfg_sanitize, cfg_target_abi, cfg_target_compact, @@ -661,6 +663,7 @@ symbols! { dyn_metadata, dyn_star, dyn_trait, + dynamic_no_pic: "dynamic-no-pic", e, edition_panic, effects, @@ -1115,6 +1118,8 @@ symbols! { path, pattern_parentheses, phantom_data, + pic, + pie, pin, platform_intrinsics, plugin, @@ -1223,6 +1228,7 @@ symbols! { register_tool, relaxed_adts, relaxed_struct_unsize, + relocation_model, rem, rem_assign, repr, @@ -1243,6 +1249,8 @@ symbols! { rintf64, riscv_target_feature, rlib, + ropi, + ropi_rwpi: "ropi-rwpi", rotate_left, rotate_right, roundevenf32, @@ -1354,6 +1362,7 @@ symbols! { rustdoc_missing_doc_code_examples, rustfmt, rvalue_static_promotion, + rwpi, s, safety, sanitize, diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs index c0f1827ad3f..400030ca0c6 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs @@ -11,6 +11,7 @@ pub fn target() -> Target { features: "+strict-align,+v6".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), ..super::linux_gnu_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs index 79b8958c22a..6228fb15a83 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs @@ -11,6 +11,7 @@ pub fn target() -> Target { features: "+strict-align,+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), ..super::linux_gnu_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs index 4836f3cf720..1d66515a72e 100644 --- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs @@ -13,6 +13,7 @@ pub fn target() -> Target { endian: Endian::Big, max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), ..super::linux_gnu_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs index 1de63a920c8..cffebcc9581 100644 --- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs @@ -12,6 +12,7 @@ pub fn target() -> Target { // Atomic operations provided by compiler-builtins max_atomic_width: Some(32), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), has_thumb_interworking: true, ..super::linux_gnu_base::opts() }, diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs index b7cfccc8b3d..4a8aa31576f 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs @@ -13,6 +13,7 @@ pub fn target() -> Target { features: "+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), ..super::freebsd_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs index 903042d7e7a..73ae212a7a6 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs @@ -14,6 +14,7 @@ pub fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), + llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), ..super::linux_gnu_base::opts() }, } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index af2b96ccb51..31b6961bb62 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -42,7 +42,7 @@ use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_fs_util::try_canonicalize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use serde_json::Value; use std::borrow::Cow; use std::collections::BTreeMap; @@ -655,6 +655,43 @@ pub enum RelocModel { RopiRwpi, } +impl RelocModel { + pub fn desc(&self) -> &str { + match *self { + RelocModel::Static => "static", + RelocModel::Pic => "pic", + RelocModel::Pie => "pie", + RelocModel::DynamicNoPic => "dynamic-no-pic", + RelocModel::Ropi => "ropi", + RelocModel::Rwpi => "rwpi", + RelocModel::RopiRwpi => "ropi-rwpi", + } + } + pub const fn desc_symbol(&self) -> Symbol { + match *self { + RelocModel::Static => kw::Static, + RelocModel::Pic => sym::pic, + RelocModel::Pie => sym::pie, + RelocModel::DynamicNoPic => sym::dynamic_no_pic, + RelocModel::Ropi => sym::ropi, + RelocModel::Rwpi => sym::rwpi, + RelocModel::RopiRwpi => sym::ropi_rwpi, + } + } + + pub const fn all() -> [Symbol; 7] { + [ + RelocModel::Static.desc_symbol(), + RelocModel::Pic.desc_symbol(), + RelocModel::Pie.desc_symbol(), + RelocModel::DynamicNoPic.desc_symbol(), + RelocModel::Ropi.desc_symbol(), + RelocModel::Rwpi.desc_symbol(), + RelocModel::RopiRwpi.desc_symbol(), + ] + } +} + impl FromStr for RelocModel { type Err = (); @@ -674,16 +711,7 @@ impl FromStr for RelocModel { impl ToJson for RelocModel { fn to_json(&self) -> Json { - match *self { - RelocModel::Static => "static", - RelocModel::Pic => "pic", - RelocModel::Pie => "pie", - RelocModel::DynamicNoPic => "dynamic-no-pic", - RelocModel::Ropi => "ropi", - RelocModel::Rwpi => "rwpi", - RelocModel::RopiRwpi => "ropi-rwpi", - } - .to_json() + self.desc().to_json() } } @@ -1922,6 +1950,9 @@ pub struct TargetOptions { /// Use platform dependent mcount function pub mcount: StaticCow<str>, + /// Use LLVM intrinsic for mcount function name + pub llvm_mcount_intrinsic: Option<StaticCow<str>>, + /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers pub llvm_abiname: StaticCow<str>, @@ -2183,6 +2214,7 @@ impl Default for TargetOptions { override_export_symbols: None, merge_functions: MergeFunctions::Aliases, mcount: "mcount".into(), + llvm_mcount_intrinsic: None, llvm_abiname: "".into(), relax_elf_relocations: false, llvm_args: cvs![], @@ -2840,6 +2872,7 @@ impl Target { key!(override_export_symbols, opt_list); key!(merge_functions, MergeFunctions)?; key!(mcount = "target-mcount"); + key!(llvm_mcount_intrinsic, optional); key!(llvm_abiname); key!(relax_elf_relocations, bool); key!(llvm_args, list); @@ -3096,6 +3129,7 @@ impl ToJson for Target { target_option_val!(override_export_symbols); target_option_val!(merge_functions); target_option_val!(mcount, "target-mcount"); + target_option_val!(llvm_mcount_intrinsic); target_option_val!(llvm_abiname); target_option_val!(relax_elf_relocations); target_option_val!(llvm_args); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 0990b9bee90..523841951b0 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // created inside of the query directly instead of returning them to the // caller. let prev_universe = self.infcx.universe(); - let universes_created_in_query = response.max_universe.index() + 1; + let universes_created_in_query = response.max_universe.index(); for _ in 0..universes_created_in_query { self.infcx.create_next_universe(); } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 41aac02eaa9..ffe6d637387 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -89,6 +89,7 @@ #![allow(explicit_outlives_requirements)] #![warn(multiple_supertrait_upcastable)] #![cfg_attr(not(bootstrap), allow(internal_features))] +#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] // // Library features: // tidy-alphabetical-start diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e2a2fe932ab..476a4fea54f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -153,7 +153,7 @@ macro_rules! acquire { /// /// ## `Deref` behavior /// -/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait), +/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait), /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name /// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated /// functions, called using [fully qualified syntax]: @@ -187,7 +187,6 @@ macro_rules! acquire { /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [atomic]: core::sync::atomic -/// [deref]: core::ops::Deref /// [downgrade]: Arc::downgrade /// [upgrade]: Weak::upgrade /// [RefCell\<T>]: core::cell::RefCell @@ -1495,7 +1494,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// alignment as `T`. This is trivially true if `U` is `T`. /// Note that if `U` is not `T` but has the same size and alignment, this is /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what + /// [`mem::transmute`] for more information on what /// restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by `alloc` @@ -1507,7 +1506,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// even if the returned `Arc<T>` is never accessed. /// /// [into_raw]: Arc::into_raw - /// [transmute]: core::mem::transmute /// /// # Examples /// diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 92e38df4049..163a65c909e 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -253,7 +253,7 @@ impl CStr { /// ``` /// /// [valid]: core::ptr#safety - #[inline] + #[inline] // inline is necessary for codegen to see strlen. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")] @@ -280,6 +280,8 @@ impl CStr { len } + // `inline` is necessary for codegen to see strlen. + #[inline] fn strlen_rt(s: *const c_char) -> usize { extern "C" { /// Provided by libc or compiler_builtins. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 48c3c1f2123..a2729b3743c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -97,6 +97,8 @@ #![allow(incomplete_features)] #![warn(multiple_supertrait_upcastable)] #![cfg_attr(not(bootstrap), allow(internal_features))] +// Do not check link redundancy on bootstraping phase +#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] // // Library features: // tidy-alphabetical-start diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 1199d09b563..1f43520e1b3 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2126,6 +2126,7 @@ macro_rules! int_impl { /// assert_eq!(a.rem_euclid(-b), 3); /// assert_eq!((-a).rem_euclid(-b), 1); /// ``` + #[doc(alias = "modulo", alias = "mod")] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 2136d29255f..81148c7cc51 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2024,6 +2024,7 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")] /// ``` + #[doc(alias = "modulo", alias = "mod")] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index a083b65604d..be173a7ace6 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -49,12 +49,14 @@ use crate::sys; /// ``` /// /// In other words, if two keys are equal, their hashes must be equal. +/// Violating this property is a logic error. /// -/// It is a logic error for a key to be modified in such a way that the key's +/// It is also a logic error for a key to be modified in such a way that the key's /// hash, as determined by the [`Hash`] trait, or its equality, as determined by /// the [`Eq`] trait, changes while it is in the map. This is normally only /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// The behavior resulting from such a logic error is not specified, but will +/// +/// The behavior resulting from either logic error is not specified, but will /// be encapsulated to the `HashMap` that observed the logic error and not /// result in undefined behavior. This could include panics, incorrect results, /// aborts, memory leaks, and non-termination. diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 959403e1644..6d85b26af5f 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -24,13 +24,14 @@ use super::map::{map_try_reserve_error, RandomState}; /// ``` /// /// In other words, if two keys are equal, their hashes must be equal. +/// Violating this property is a logic error. /// -/// -/// It is a logic error for a key to be modified in such a way that the key's +/// It is also a logic error for a key to be modified in such a way that the key's /// hash, as determined by the [`Hash`] trait, or its equality, as determined by /// the [`Eq`] trait, changes while it is in the map. This is normally only /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// The behavior resulting from such a logic error is not specified, but will +/// +/// The behavior resulting from either logic error is not specified, but will /// be encapsulated to the `HashSet` that observed the logic error and not /// result in undefined behavior. This could include panics, incorrect results, /// aborts, memory leaks, and non-termination. diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 7bc3af1793e..375ff2d2450 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -10,7 +10,7 @@ use crate::fmt::{self, Write}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::error::Error; #[unstable(feature = "error_generic_member_access", issue = "99301")] -pub use core::error::{request_ref, Request}; +pub use core::error::{request_ref, request_value, Request}; mod private { // This is a hack to prevent `type_id` from being overridden by `Error` diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index a53b8535213..a659b552f47 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -61,6 +61,7 @@ impl f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[doc(alias = "ceiling")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -135,6 +136,7 @@ impl f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[doc(alias = "truncate")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -321,6 +323,7 @@ impl f32 { /// // limitation due to round-off error /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[doc(alias = "modulo", alias = "mod")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] @@ -672,6 +675,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[doc(alias = "arcsin")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -694,6 +698,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[doc(alias = "arccos")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -715,6 +720,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[doc(alias = "arctan")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -772,6 +778,7 @@ impl f32 { /// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON); /// ``` + #[doc(alias = "sincos")] #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -904,6 +911,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[doc(alias = "arcsinh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -926,6 +934,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[doc(alias = "arccosh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -950,6 +959,7 @@ impl f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` + #[doc(alias = "arctanh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index a1cec22c97a..721e1fb754e 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -61,6 +61,7 @@ impl f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[doc(alias = "ceiling")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -135,6 +136,7 @@ impl f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[doc(alias = "truncate")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -321,6 +323,7 @@ impl f64 { /// // limitation due to round-off error /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[doc(alias = "modulo", alias = "mod")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] @@ -672,6 +675,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[doc(alias = "arcsin")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -694,6 +698,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[doc(alias = "arccos")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -715,6 +720,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[doc(alias = "arctan")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -772,6 +778,7 @@ impl f64 { /// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_1 < 1e-10); /// ``` + #[doc(alias = "sincos")] #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -904,6 +911,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[doc(alias = "arcsinh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -926,6 +934,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[doc(alias = "arccosh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -950,6 +959,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[doc(alias = "arctanh")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ac4ce222fba..58684ffe500 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -223,6 +223,7 @@ #![cfg_attr(not(bootstrap), allow(internal_features))] #![deny(rustc::existing_doc_keyword)] #![deny(fuzzy_provenance_casts)] +#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` #![deny(ffi_unwind_calls)] // std may use features in a platform-specific way diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index 2329426ad1d..58afca088ef 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -25,10 +25,6 @@ pub fn errno() -> i32 { /// Gets a detailed string description for the given error number. pub fn error_string(mut errnum: i32) -> String { - // This value is calculated from the macro - // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) - let langId = 0x0800 as c::DWORD; - let mut buf = [0 as c::WCHAR; 2048]; unsafe { @@ -56,13 +52,13 @@ pub fn error_string(mut errnum: i32) -> String { flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS, module, errnum as c::DWORD, - langId, + 0, buf.as_mut_ptr(), buf.len() as c::DWORD, ptr::null(), ) as usize; if res == 0 { - // Sometimes FormatMessageW can fail e.g., system doesn't like langId, + // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId, let fm_err = errno(); return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})"); } diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs index 15042fc3bee..04667439660 100644 --- a/library/std/src/sys_common/thread_parking/id.rs +++ b/library/std/src/sys_common/thread_parking/id.rs @@ -56,18 +56,14 @@ impl Parker { self.init_tid(); // Changes NOTIFIED to EMPTY and EMPTY to PARKED. - let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); - if state == PARKED { + let state = self.state.fetch_sub(1, Acquire); + if state == EMPTY { // Loop to guard against spurious wakeups. - while state == PARKED { + // The state must be reset with acquire ordering to ensure that all + // calls to `unpark` synchronize with this thread. + while self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed).is_err() { park(self.state.as_ptr().addr()); - state = self.state.load(Acquire); } - - // Since the state change has already been observed with acquire - // ordering, the state can be reset with a relaxed store instead - // of a swap. - self.state.store(EMPTY, Relaxed); } } @@ -78,8 +74,7 @@ impl Parker { if state == PARKED { park_timeout(dur, self.state.as_ptr().addr()); // Swap to ensure that we observe all state changes with acquire - // ordering, even if the state has been changed after the timeout - // occurred. + // ordering. self.state.swap(EMPTY, Acquire); } } diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index fd57b079644..f15e6e451e7 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it warning: 1 warning emitted ``` + +## `redundant_explicit_links` + +This lint is **warned by default**. It detects explicit links that are same +as computed automatic links. +This usually means the explicit links is removeable. For example: + +```rust +#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default. + +/// add takes 2 [`usize`](usize) and performs addition +/// on them, then returns result. +pub fn add(left: usize, right: usize) -> usize { + left + right +} +``` + +Which will give: + +```text +error: redundant explicit rustdoc link + --> src/lib.rs:3:27 + | +3 | /// add takes 2 [`usize`](usize) and performs addition + | ^^^^^ + | + = note: Explicit link does not affect the original link +note: the lint level is defined here + --> src/lib.rs:1:9 + | +1 | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: Remove explicit link instead +``` diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0ba2d992392..98cc38a10d4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -50,7 +50,7 @@ use crate::html::render::small_url_encode; use crate::html::toc::TocBuilder; use pulldown_cmark::{ - html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, + html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag, }; #[cfg(test)] @@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin pub(crate) struct MarkdownLink { pub kind: LinkType, pub link: String, + pub display_text: Option<String>, pub range: MarkdownLinkRange, } @@ -1263,8 +1264,8 @@ impl MarkdownLinkRange { } } -pub(crate) fn markdown_links<R>( - md: &str, +pub(crate) fn markdown_links<'md, R>( + md: &'md str, preprocess_link: impl Fn(MarkdownLink) -> Option<R>, ) -> Vec<R> { if md.is_empty() { @@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>( MarkdownLinkRange::Destination(range.clone()) }; - Parser::new_with_broken_link_callback( + let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut event_iter = Parser::new_with_broken_link_callback( md, main_body_opts(), - Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))), + Some(&mut broken_link_callback), ) - .into_offset_iter() - .filter_map(|(event, span)| match event { - Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { - let range = match link_type { - // Link is pulled from the link itself. - LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => { - span_for_offset_backward(span, b'[', b']') - } - LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'), - LinkType::Inline => span_for_offset_backward(span, b'(', b')'), - // Link is pulled from elsewhere in the document. - LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => { - span_for_link(&dest, span) + .into_offset_iter(); + let mut links = Vec::new(); + + while let Some((event, span)) = event_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { + let range = match link_type { + // Link is pulled from the link itself. + LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => { + span_for_offset_backward(span, b'[', b']') + } + LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'), + LinkType::Inline => span_for_offset_backward(span, b'(', b')'), + // Link is pulled from elsewhere in the document. + LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => { + span_for_link(&dest, span) + } + LinkType::Autolink | LinkType::Email => unreachable!(), + }; + + let display_text = if matches!( + link_type, + LinkType::Inline + | LinkType::ReferenceUnknown + | LinkType::Reference + | LinkType::Shortcut + | LinkType::ShortcutUnknown + ) { + collect_link_data(&mut event_iter) + } else { + None + }; + + if let Some(link) = preprocess_link(MarkdownLink { + kind: link_type, + link: dest.into_string(), + display_text, + range, + }) { + links.push(link); } - LinkType::Autolink | LinkType::Email => unreachable!(), - }; - preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() }) + } + _ => {} } - _ => None, - }) - .collect() + } + + links +} + +/// Collects additional data of link. +fn collect_link_data<'input, 'callback>( + event_iter: &mut OffsetIter<'input, 'callback>, +) -> Option<String> { + let mut display_text: Option<String> = None; + let mut append_text = |text: CowStr<'_>| { + if let Some(display_text) = &mut display_text { + display_text.push_str(&text); + } else { + display_text = Some(text.to_string()); + } + }; + + while let Some((event, _span)) = event_iter.next() { + match event { + Event::Text(text) => { + append_text(text); + } + Event::Code(code) => { + append_text(code); + } + Event::End(_) => { + break; + } + _ => {} + } + } + + display_text } #[derive(Debug)] diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 749c1ff51bf..d45040e348a 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -185,6 +185,17 @@ declare_rustdoc_lint! { "detects unescaped backticks in doc comments" } +declare_rustdoc_lint! { + /// This lint is **warned by default**. It detects explicit links that are same + /// as computed automatic links. This usually means the explicit links is removeable. + /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book]. + /// + /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links + REDUNDANT_EXPLICIT_LINKS, + Warn, + "detects redundant explicit links in doc comments" +} + pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| { vec![ BROKEN_INTRA_DOC_LINKS, @@ -197,6 +208,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| { BARE_URLS, MISSING_CRATE_LEVEL_DOCS, UNESCAPED_BACKTICKS, + REDUNDANT_EXPLICIT_LINKS, ] }); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 26ff64f06a3..36872266ee1 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -994,7 +994,7 @@ impl LinkCollector<'_, '_> { _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(), }; for md_link in preprocessed_markdown_links(&doc) { - let link = self.resolve_link(item, item_id, module_id, &doc, &md_link); + let link = self.resolve_link(&doc, item, item_id, module_id, &md_link); if let Some(link) = link { self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link); } @@ -1007,13 +1007,12 @@ impl LinkCollector<'_, '_> { /// FIXME(jynelson): this is way too many arguments fn resolve_link( &mut self, + dox: &String, item: &Item, item_id: DefId, module_id: DefId, - dox: &str, - link: &PreprocessedMarkdownLink, + PreprocessedMarkdownLink(pp_link, ori_link): &PreprocessedMarkdownLink, ) -> Option<ItemLink> { - let PreprocessedMarkdownLink(pp_link, ori_link) = link; trace!("considering link '{}'", ori_link.link); let diag_info = DiagnosticInfo { @@ -1022,7 +1021,6 @@ impl LinkCollector<'_, '_> { ori_link: &ori_link.link, link_range: ori_link.range.clone(), }; - let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?; let disambiguator = *disambiguator; @@ -1040,8 +1038,24 @@ impl LinkCollector<'_, '_> { // resolutions are cached, for other links we want to report an error every // time so they are not cached. matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut), + false, )?; + if ori_link.display_text.is_some() { + self.resolve_display_text( + path_str, + ResolutionInfo { + item_id, + module_id, + dis: disambiguator, + path_str: ori_link.display_text.clone()?.into_boxed_str(), + extra_fragment: extra_fragment.clone(), + }, + &ori_link, + &diag_info, + ); + } + // Check for a primitive which might conflict with a module // Report the ambiguity and require that the user specify which one they meant. // FIXME: could there ever be a primitive not in the type namespace? @@ -1221,6 +1235,9 @@ impl LinkCollector<'_, '_> { // If errors are cached then they are only reported on first occurrence // which we want in some cases but not in others. cache_errors: bool, + // If this call is intended to be recoverable, then pass true to silence. + // This is only recoverable when path is failed to resolved. + recoverable: bool, ) -> Option<(Res, Option<UrlFragment>)> { if let Some(res) = self.visited_links.get(&key) { if res.is_some() || cache_errors { @@ -1228,7 +1245,7 @@ impl LinkCollector<'_, '_> { } } - let mut candidates = self.resolve_with_disambiguator(&key, diag.clone()); + let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable); // 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. @@ -1279,6 +1296,9 @@ impl LinkCollector<'_, '_> { &mut self, key: &ResolutionInfo, diag: DiagnosticInfo<'_>, + // If this call is intended to be recoverable, then pass true to silence. + // This is only recoverable when path is failed to resolved. + recoverable: bool, ) -> Vec<(Res, Option<DefId>)> { let disambiguator = key.dis; let path_str = &key.path_str; @@ -1308,7 +1328,9 @@ impl LinkCollector<'_, '_> { } } } - resolution_failure(self, diag, path_str, disambiguator, smallvec![err]); + if !recoverable { + resolution_failure(self, diag, path_str, disambiguator, smallvec![err]); + } return vec![]; } } @@ -1345,13 +1367,15 @@ impl LinkCollector<'_, '_> { .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc }); if len == 0 { - resolution_failure( - self, - diag, - path_str, - disambiguator, - candidates.into_iter().filter_map(|res| res.err()).collect(), - ); + if !recoverable { + resolution_failure( + self, + diag, + path_str, + disambiguator, + candidates.into_iter().filter_map(|res| res.err()).collect(), + ); + } return vec![]; } else if len == 1 { candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>() @@ -1372,6 +1396,63 @@ impl LinkCollector<'_, '_> { } } } + + /// Resolve display text if the provided link has separated parts of links. + /// + /// For example: + /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has + /// separated parts of links. + fn resolve_display_text( + &mut self, + explicit_link: &Box<str>, + display_res_info: ResolutionInfo, + ori_link: &MarkdownLink, + diag_info: &DiagnosticInfo<'_>, + ) { + // Check if explicit resolution's path is same as resolution of original link's display text path, see + // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases. + // + // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated + // into explicit path. + if !matches!( + ori_link.kind, + LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown + ) { + return; + } + + // Algorithm to check if display text could possibly be the explicit link: + // + // Consider 2 links which are display text and explicit link, pick the shorter + // one as symbol and longer one as full qualified path, and tries to match symbol + // to the full qualified path's last symbol. + // + // Otherwise, check if 2 links are same, if so, skip the resolve process. + // + // Notice that this algorithm is passive, might possibly miss actual redudant cases. + let explicit_link = &explicit_link.to_string(); + let display_text = ori_link.display_text.as_ref().unwrap(); + let display_len = display_text.len(); + let explicit_len = explicit_link.len(); + + if display_len == explicit_len { + // Whether they are same or not, skip the resolve process. + return; + } + + if (explicit_len >= display_len + && &explicit_link[(explicit_len - display_len)..] == display_text) + || (display_len >= explicit_len + && &display_text[(display_len - explicit_len)..] == explicit_link) + { + self.resolve_with_disambiguator_cached( + display_res_info, + diag_info.clone(), // this struct should really be Copy, but Range is not :( + false, + true, + ); + } + } } /// Get the section of a link between the backticks, diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index e653207b9b6..c6d5b7bd346 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -4,6 +4,7 @@ mod bare_urls; mod check_code_block_syntax; mod html_tags; +mod redundant_explicit_links; mod unescaped_backticks; use super::Pass; @@ -29,6 +30,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> { check_code_block_syntax::visit_item(self.cx, item); html_tags::visit_item(self.cx, item); unescaped_backticks::visit_item(self.cx, item); + redundant_explicit_links::visit_item(self.cx, item); self.visit_item_recur(item) } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs new file mode 100644 index 00000000000..ef0f8716aa8 --- /dev/null +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -0,0 +1,352 @@ +use std::ops::Range; + +use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, OffsetIter, Parser, Tag}; +use rustc_ast::NodeId; +use rustc_errors::SuggestionStyle; +use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; +use rustc_hir::HirId; +use rustc_lint_defs::Applicability; +use rustc_span::Symbol; + +use crate::clean::utils::find_nearest_parent_module; +use crate::clean::utils::inherits_doc_hidden; +use crate::clean::Item; +use crate::core::DocContext; +use crate::html::markdown::main_body_opts; +use crate::passes::source_span_for_markdown_range; + +#[derive(Debug)] +struct LinkData { + resolvable_link: Option<String>, + resolvable_link_range: Option<Range<usize>>, + display_link: String, +} + +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { + let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { + // If non-local, no need to check anything. + return; + }; + + let doc = item.doc_value(); + if doc.is_empty() { + return; + } + + if item.link_names(&cx.cache).is_empty() { + // If there's no link names in this item, + // then we skip resolution querying to + // avoid from panicking. + return; + } + + let Some(item_id) = item.def_id() else { + return; + }; + let Some(local_item_id) = item_id.as_local() else { + return; + }; + + let is_hidden = !cx.render_options.document_hidden + && (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None)); + if is_hidden { + return; + } + let is_private = !cx.render_options.document_private + && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id); + if is_private { + return; + } + + check_redundant_explicit_link(cx, item, hir_id, &doc); +} + +fn check_redundant_explicit_link<'md>( + cx: &DocContext<'_>, + item: &Item, + hir_id: HirId, + doc: &'md str, +) -> Option<()> { + let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut offset_iter = Parser::new_with_broken_link_callback( + &doc, + main_body_opts(), + Some(&mut broken_line_callback), + ) + .into_offset_iter(); + let item_id = item.def_id()?; + let module_id = match cx.tcx.def_kind(item_id) { + DefKind::Mod if item.inner_docs(cx.tcx) => item_id, + _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(), + }; + let resolutions = cx.tcx.doc_link_resolutions(module_id); + + while let Some((event, link_range)) = offset_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) => { + let link_data = collect_link_data(&mut offset_iter); + + if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { + if &link_data.display_link.replace("`", "") != resolvable_link { + // Skips if display link does not match to actual + // resolvable link, usually happens if display link + // has several segments, e.g. + // [this is just an `Option`](Option) + continue; + } + } + + let explicit_link = dest.to_string(); + let display_link = link_data.resolvable_link.clone()?; + let explicit_len = explicit_link.len(); + let display_len = display_link.len(); + + if (explicit_len >= display_len + && &explicit_link[(explicit_len - display_len)..] == display_link) + || (display_len >= explicit_len + && &display_link[(display_len - explicit_len)..] == explicit_link) + { + match link_type { + LinkType::Inline | LinkType::ReferenceUnknown => { + check_inline_or_reference_unknown_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + dest.to_string(), + link_data, + if link_type == LinkType::Inline { + (b'(', b')') + } else { + (b'[', b']') + }, + ); + } + LinkType::Reference => { + check_reference_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + &dest, + link_data, + ); + } + _ => {} + } + } + } + _ => {} + } + } + + None +} + +/// FIXME(ChAoSUnItY): Too many arguments. +fn check_inline_or_reference_unknown_redundancy( + cx: &DocContext<'_>, + item: &Item, + hir_id: HirId, + doc: &str, + resolutions: &DocLinkResMap, + link_range: Range<usize>, + dest: String, + link_data: LinkData, + (open, close): (u8, u8), +) -> Option<()> { + let (resolvable_link, resolvable_link_range) = + (&link_data.resolvable_link?, &link_data.resolvable_link_range?); + let (dest_res, display_res) = + (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + + if dest_res == display_res { + let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs) + .unwrap_or(item.attr_span(cx.tcx)); + let explicit_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &offset_explicit_range(doc, link_range, open, close), + &item.attrs, + )?; + let display_span = + source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?; + + cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { + lint.span_label(explicit_span, "explicit target is redundant") + .span_label(display_span, "because label contains path that resolves to same destination") + .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links") + .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways); + + lint + }); + } + + None +} + +/// FIXME(ChAoSUnItY): Too many arguments. +fn check_reference_redundancy( + cx: &DocContext<'_>, + item: &Item, + hir_id: HirId, + doc: &str, + resolutions: &DocLinkResMap, + link_range: Range<usize>, + dest: &CowStr<'_>, + link_data: LinkData, +) -> Option<()> { + let (resolvable_link, resolvable_link_range) = + (&link_data.resolvable_link?, &link_data.resolvable_link_range?); + let (dest_res, display_res) = + (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + + if dest_res == display_res { + let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs) + .unwrap_or(item.attr_span(cx.tcx)); + let explicit_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &offset_explicit_range(doc, link_range.clone(), b'[', b']'), + &item.attrs, + )?; + let display_span = + source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?; + let def_span = source_span_for_markdown_range( + cx.tcx, + &doc, + &offset_reference_def_range(doc, dest, link_range), + &item.attrs, + )?; + + cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { + lint.span_label(explicit_span, "explicit target is redundant") + .span_label(display_span, "because label contains path that resolves to same destination") + .span_note(def_span, "referenced explicit link target defined here") + .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links") + .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways); + + lint + }); + } + + None +} + +fn find_resolution(resolutions: &DocLinkResMap, path: &str) -> Option<Res<NodeId>> { + [Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS] + .into_iter() + .find_map(|ns| resolutions.get(&(Symbol::intern(path), ns)).copied().flatten()) +} + +/// Collects all neccessary data of link. +fn collect_link_data(offset_iter: &mut OffsetIter<'_, '_>) -> LinkData { + let mut resolvable_link = None; + let mut resolvable_link_range = None; + let mut display_link = String::new(); + + while let Some((event, range)) = offset_iter.next() { + match event { + Event::Text(code) => { + let code = code.to_string(); + display_link.push_str(&code); + resolvable_link = Some(code); + resolvable_link_range = Some(range); + } + Event::Code(code) => { + let code = code.to_string(); + display_link.push('`'); + display_link.push_str(&code); + display_link.push('`'); + resolvable_link = Some(code); + resolvable_link_range = Some(range); + } + Event::End(_) => { + break; + } + _ => {} + } + } + + LinkData { resolvable_link, resolvable_link_range, display_link } +} + +fn offset_explicit_range(md: &str, link_range: Range<usize>, open: u8, close: u8) -> Range<usize> { + let mut open_brace = !0; + let mut close_brace = !0; + for (i, b) in md.as_bytes()[link_range.clone()].iter().copied().enumerate().rev() { + let i = i + link_range.start; + if b == close { + close_brace = i; + break; + } + } + + if close_brace < link_range.start || close_brace >= link_range.end { + return link_range; + } + + let mut nesting = 1; + + for (i, b) in md.as_bytes()[link_range.start..close_brace].iter().copied().enumerate().rev() { + let i = i + link_range.start; + if b == close { + nesting += 1; + } + if b == open { + nesting -= 1; + } + if nesting == 0 { + open_brace = i; + break; + } + } + + assert!(open_brace != close_brace); + + if open_brace < link_range.start || open_brace >= link_range.end { + return link_range; + } + // do not actually include braces in the span + (open_brace + 1)..close_brace +} + +fn offset_reference_def_range( + md: &str, + dest: &CowStr<'_>, + link_range: Range<usize>, +) -> Range<usize> { + // For diagnostics, we want to underline the link's definition but `span` will point at + // where the link is used. This is a problem for reference-style links, where the definition + // is separate from the usage. + + match dest { + // `Borrowed` variant means the string (the link's destination) may come directly from + // the markdown text and we can locate the original link destination. + // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources, + // so `locate()` can fall back to use `span`. + CowStr::Borrowed(s) => { + // FIXME: remove this function once pulldown_cmark can provide spans for link definitions. + unsafe { + let s_start = dest.as_ptr(); + let s_end = s_start.add(s.len()); + let md_start = md.as_ptr(); + let md_end = md_start.add(md.len()); + if md_start <= s_start && s_end <= md_end { + let start = s_start.offset_from(md_start) as usize; + let end = s_end.offset_from(md_start) as usize; + start..end + } else { + link_range + } + } + } + + // For anything else, we can only use the provided range. + CowStr::Boxed(_) | CowStr::Inlined(_) => link_range, + } +} diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 7c3904d6c3ed54e8a413023519b55a536ad44d5 +Subproject 80eca0e58fb2ff52c1e94fc191b55b37ed73e0e diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile index c88ec1e6cb3..3bc3d7d1428 100644 --- a/tests/run-make/optimization-remarks-dir-pgo/Makefile +++ b/tests/run-make/optimization-remarks-dir-pgo/Makefile @@ -1,5 +1,6 @@ # needs-profiler-support # ignore-windows-gnu +# ignore-cross-compile # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works # properly. Since we only have GCC on the CI ignore the test for now. diff --git a/tests/rustdoc-ui/lints/inline-doc-link.rs b/tests/rustdoc-ui/lints/inline-doc-link.rs new file mode 100644 index 00000000000..596f89be3d6 --- /dev/null +++ b/tests/rustdoc-ui/lints/inline-doc-link.rs @@ -0,0 +1,13 @@ +// Regression test for <https://github.com/rust-lang/rust/pull/113167> + +// check-pass +#![deny(rustdoc::redundant_explicit_links)] + +mod m { + pub enum ValueEnum {} +} +mod m2 { + /// [`ValueEnum`] + pub use crate::m::ValueEnum; +} +pub use m2::ValueEnum; diff --git a/tests/rustdoc-ui/lints/no-redundancy.rs b/tests/rustdoc-ui/lints/no-redundancy.rs new file mode 100644 index 00000000000..e3358728b1b --- /dev/null +++ b/tests/rustdoc-ui/lints/no-redundancy.rs @@ -0,0 +1,7 @@ +// check-pass + +#![deny(rustdoc::redundant_explicit_links)] + +/// [Vec][std::vec::Vec#examples] should not warn, because it's not actually redundant! +/// [This is just an `Option`][std::option::Option] has different display content to actual link! +pub fn func() {} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed new file mode 100644 index 00000000000..900234e31e9 --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed @@ -0,0 +1,158 @@ +// run-rustfix + +#![deny(rustdoc::redundant_explicit_links)] + +pub fn dummy_target() {} + +/// [dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`] +//~^ ERROR redundant explicit link target +/// +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`] TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_inline() {} + +/// [`Vec<T>`](Vec) +/// [`Vec<T>`](std::vec::Vec) +pub fn should_not_warn_inline() {} + +/// [dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`] +//~^ ERROR redundant explicit link target +/// +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`] TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_reference_unknown() {} + +/// [`Vec<T>`][Vec] +/// [`Vec<T>`][std::vec::Vec] +pub fn should_not_warn_reference_unknown() {} + +/// [dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`] +//~^ ERROR redundant explicit link target +/// +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`] +//~^ ERROR redundant explicit link target +/// +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [usize] +//~^ ERROR redundant explicit link target +/// [`usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`] TEXT +//~^ ERROR redundant explicit link target +/// +/// [dummy_target]: dummy_target +/// [Vec]: Vec +/// [std::vec::Vec]: Vec +/// [usize]: usize +/// [std::primitive::usize]: usize +pub fn should_warn_reference() {} + +/// [`Vec<T>`]: Vec +/// [`Vec<T>`]: std::vec::Vec +pub fn should_not_warn_reference() {} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs new file mode 100644 index 00000000000..13feb85e051 --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs @@ -0,0 +1,158 @@ +// run-rustfix + +#![deny(rustdoc::redundant_explicit_links)] + +pub fn dummy_target() {} + +/// [dummy_target](dummy_target) +//~^ ERROR redundant explicit link target +/// [`dummy_target`](dummy_target) +//~^ ERROR redundant explicit link target +/// +/// [Vec](Vec) +//~^ ERROR redundant explicit link target +/// [`Vec`](Vec) +//~^ ERROR redundant explicit link target +/// [Vec](std::vec::Vec) +//~^ ERROR redundant explicit link target +/// [`Vec`](std::vec::Vec) +//~^ ERROR redundant explicit link target +/// [std::vec::Vec](Vec) +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`](Vec) +//~^ ERROR redundant explicit link target +/// [std::vec::Vec](std::vec::Vec) +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`](std::vec::Vec) +//~^ ERROR redundant explicit link target +/// +/// [usize](usize) +//~^ ERROR redundant explicit link target +/// [`usize`](usize) +//~^ ERROR redundant explicit link target +/// [usize](std::primitive::usize) +//~^ ERROR redundant explicit link target +/// [`usize`](std::primitive::usize) +//~^ ERROR redundant explicit link target +/// [std::primitive::usize](usize) +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`](usize) +//~^ ERROR redundant explicit link target +/// [std::primitive::usize](std::primitive::usize) +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`](std::primitive::usize) +//~^ ERROR redundant explicit link target +/// +/// [dummy_target](dummy_target) TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`](dummy_target) TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_inline() {} + +/// [`Vec<T>`](Vec) +/// [`Vec<T>`](std::vec::Vec) +pub fn should_not_warn_inline() {} + +/// [dummy_target][dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`][dummy_target] +//~^ ERROR redundant explicit link target +/// +/// [Vec][Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`][Vec] +//~^ ERROR redundant explicit link target +/// [Vec][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec][Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`][Vec] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// +/// [usize][usize] +//~^ ERROR redundant explicit link target +/// [`usize`][usize] +//~^ ERROR redundant explicit link target +/// [usize][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`usize`][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize][usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`][usize] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target][dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`][dummy_target] TEXT +//~^ ERROR redundant explicit link target +pub fn should_warn_reference_unknown() {} + +/// [`Vec<T>`][Vec] +/// [`Vec<T>`][std::vec::Vec] +pub fn should_not_warn_reference_unknown() {} + +/// [dummy_target][dummy_target] +//~^ ERROR redundant explicit link target +/// [`dummy_target`][dummy_target] +//~^ ERROR redundant explicit link target +/// +/// [Vec][Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`][Vec] +//~^ ERROR redundant explicit link target +/// [Vec][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`Vec`][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec][Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`][Vec] +//~^ ERROR redundant explicit link target +/// [std::vec::Vec][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// [`std::vec::Vec`][std::vec::Vec] +//~^ ERROR redundant explicit link target +/// +/// [usize][usize] +//~^ ERROR redundant explicit link target +/// [`usize`][usize] +//~^ ERROR redundant explicit link target +/// [usize][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`usize`][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize][usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`][usize] +//~^ ERROR redundant explicit link target +/// [std::primitive::usize][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// [`std::primitive::usize`][std::primitive::usize] +//~^ ERROR redundant explicit link target +/// +/// [dummy_target][dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// [`dummy_target`][dummy_target] TEXT +//~^ ERROR redundant explicit link target +/// +/// [dummy_target]: dummy_target +/// [Vec]: Vec +/// [std::vec::Vec]: Vec +/// [usize]: usize +/// [std::primitive::usize]: usize +pub fn should_warn_reference() {} + +/// [`Vec<T>`]: Vec +/// [`Vec<T>`]: std::vec::Vec +pub fn should_not_warn_reference() {} diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr new file mode 100644 index 00000000000..34ec9be6646 --- /dev/null +++ b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr @@ -0,0 +1,1007 @@ +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:7:20 + | +LL | /// [dummy_target](dummy_target) + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/redundant_explicit_links.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [dummy_target] + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:9:22 + | +LL | /// [`dummy_target`](dummy_target) + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] + | ~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:12:11 + | +LL | /// [Vec](Vec) + | --- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:14:13 + | +LL | /// [`Vec`](Vec) + | ----- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:16:11 + | +LL | /// [Vec](std::vec::Vec) + | --- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:18:13 + | +LL | /// [`Vec`](std::vec::Vec) + | ----- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:20:21 + | +LL | /// [std::vec::Vec](Vec) + | ------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:22:23 + | +LL | /// [`std::vec::Vec`](Vec) + | --------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:24:21 + | +LL | /// [std::vec::Vec](std::vec::Vec) + | ------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:26:23 + | +LL | /// [`std::vec::Vec`](std::vec::Vec) + | --------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:29:13 + | +LL | /// [usize](usize) + | ----- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:31:15 + | +LL | /// [`usize`](usize) + | ------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:33:13 + | +LL | /// [usize](std::primitive::usize) + | ----- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:35:15 + | +LL | /// [`usize`](std::primitive::usize) + | ------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:37:29 + | +LL | /// [std::primitive::usize](usize) + | --------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:39:31 + | +LL | /// [`std::primitive::usize`](usize) + | ----------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:41:29 + | +LL | /// [std::primitive::usize](std::primitive::usize) + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:43:31 + | +LL | /// [`std::primitive::usize`](std::primitive::usize) + | ----------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:46:20 + | +LL | /// [dummy_target](dummy_target) TEXT + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [dummy_target] TEXT + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:48:22 + | +LL | /// [`dummy_target`](dummy_target) TEXT + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] TEXT + | ~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:56:20 + | +LL | /// [dummy_target][dummy_target] + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [dummy_target] + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:58:22 + | +LL | /// [`dummy_target`][dummy_target] + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] + | ~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:61:11 + | +LL | /// [Vec][Vec] + | --- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:63:13 + | +LL | /// [`Vec`][Vec] + | ----- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:65:11 + | +LL | /// [Vec][std::vec::Vec] + | --- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:67:13 + | +LL | /// [`Vec`][std::vec::Vec] + | ----- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:69:21 + | +LL | /// [std::vec::Vec][Vec] + | ------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:71:23 + | +LL | /// [`std::vec::Vec`][Vec] + | --------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:73:21 + | +LL | /// [std::vec::Vec][std::vec::Vec] + | ------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:75:23 + | +LL | /// [`std::vec::Vec`][std::vec::Vec] + | --------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:78:13 + | +LL | /// [usize][usize] + | ----- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:80:15 + | +LL | /// [`usize`][usize] + | ------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:82:13 + | +LL | /// [usize][std::primitive::usize] + | ----- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:84:15 + | +LL | /// [`usize`][std::primitive::usize] + | ------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:86:29 + | +LL | /// [std::primitive::usize][usize] + | --------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:88:31 + | +LL | /// [`std::primitive::usize`][usize] + | ----------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:90:29 + | +LL | /// [std::primitive::usize][std::primitive::usize] + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:92:31 + | +LL | /// [`std::primitive::usize`][std::primitive::usize] + | ----------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:95:20 + | +LL | /// [dummy_target][dummy_target] TEXT + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [dummy_target] TEXT + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:97:22 + | +LL | /// [`dummy_target`][dummy_target] TEXT + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] TEXT + | ~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:105:20 + | +LL | /// [dummy_target][dummy_target] + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:149:21 + | +LL | /// [dummy_target]: dummy_target + | ^^^^^^^^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [dummy_target] + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:107:22 + | +LL | /// [`dummy_target`][dummy_target] + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:149:21 + | +LL | /// [dummy_target]: dummy_target + | ^^^^^^^^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] + | ~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:110:11 + | +LL | /// [Vec][Vec] + | --- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:150:12 + | +LL | /// [Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:112:13 + | +LL | /// [`Vec`][Vec] + | ----- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:150:12 + | +LL | /// [Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:114:11 + | +LL | /// [Vec][std::vec::Vec] + | --- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:151:22 + | +LL | /// [std::vec::Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [Vec] + | ~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:116:13 + | +LL | /// [`Vec`][std::vec::Vec] + | ----- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:151:22 + | +LL | /// [std::vec::Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`Vec`] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:118:21 + | +LL | /// [std::vec::Vec][Vec] + | ------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:150:12 + | +LL | /// [Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:120:23 + | +LL | /// [`std::vec::Vec`][Vec] + | --------------- ^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:150:12 + | +LL | /// [Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:122:21 + | +LL | /// [std::vec::Vec][std::vec::Vec] + | ------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:151:22 + | +LL | /// [std::vec::Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::vec::Vec] + | ~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:124:23 + | +LL | /// [`std::vec::Vec`][std::vec::Vec] + | --------------- ^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:151:22 + | +LL | /// [std::vec::Vec]: Vec + | ^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::vec::Vec`] + | ~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:127:13 + | +LL | /// [usize][usize] + | ----- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:152:14 + | +LL | /// [usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:129:15 + | +LL | /// [`usize`][usize] + | ------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:152:14 + | +LL | /// [usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:131:13 + | +LL | /// [usize][std::primitive::usize] + | ----- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:153:30 + | +LL | /// [std::primitive::usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [usize] + | ~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:133:15 + | +LL | /// [`usize`][std::primitive::usize] + | ------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:153:30 + | +LL | /// [std::primitive::usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`usize`] + | ~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:135:29 + | +LL | /// [std::primitive::usize][usize] + | --------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:152:14 + | +LL | /// [usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:137:31 + | +LL | /// [`std::primitive::usize`][usize] + | ----------------------- ^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:152:14 + | +LL | /// [usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:139:29 + | +LL | /// [std::primitive::usize][std::primitive::usize] + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:153:30 + | +LL | /// [std::primitive::usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [std::primitive::usize] + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:141:31 + | +LL | /// [`std::primitive::usize`][std::primitive::usize] + | ----------------------- ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:153:30 + | +LL | /// [std::primitive::usize]: usize + | ^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`std::primitive::usize`] + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:144:20 + | +LL | /// [dummy_target][dummy_target] TEXT + | ------------ ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:149:21 + | +LL | /// [dummy_target]: dummy_target + | ^^^^^^^^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [dummy_target] TEXT + | ~~~~~~~~~~~~~~ + +error: redundant explicit link target + --> $DIR/redundant_explicit_links.rs:146:22 + | +LL | /// [`dummy_target`][dummy_target] TEXT + | -------------- ^^^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | +note: referenced explicit link target defined here + --> $DIR/redundant_explicit_links.rs:149:21 + | +LL | /// [dummy_target]: dummy_target + | ^^^^^^^^^^^^ + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +help: remove explicit link target + | +LL | /// [`dummy_target`] TEXT + | ~~~~~~~~~~~~~~~~ + +error: aborting due to 60 previous errors + diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs index e99cd1f3d58..e960e9f59e9 100644 --- a/tests/rustdoc-ui/unescaped_backticks.rs +++ b/tests/rustdoc-ui/unescaped_backticks.rs @@ -1,6 +1,7 @@ #![deny(rustdoc::unescaped_backticks)] #![allow(rustdoc::broken_intra_doc_links)] #![allow(rustdoc::invalid_html_tags)] +#![allow(rustdoc::redundant_explicit_links)] /// pub fn empty() {} diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index bf1f18889c4..83822f778d0 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -1,5 +1,5 @@ error: unescaped backtick - --> $DIR/unescaped_backticks.rs:186:70 + --> $DIR/unescaped_backticks.rs:187:70 | LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect = | ^ @@ -19,7 +19,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:231:13 + --> $DIR/unescaped_backticks.rs:232:13 | LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")] | ^ @@ -34,7 +34,7 @@ LL | //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:236:13 + --> $DIR/unescaped_backticks.rs:237:13 | LL | /// `cfg=... | ^ @@ -49,7 +49,7 @@ LL | /// \`cfg=... | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:240:42 + --> $DIR/unescaped_backticks.rs:241:42 | LL | /// `cfg=... and not `#[cfg_attr]` | ^ @@ -64,7 +64,7 @@ LL | /// `cfg=... and not `#[cfg_attr]\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:192:91 + --> $DIR/unescaped_backticks.rs:193:91 | LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to | ^ @@ -79,7 +79,7 @@ LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:201:34 + --> $DIR/unescaped_backticks.rs:202:34 | LL | /// in `nt_to_tokenstream` | ^ @@ -94,7 +94,7 @@ LL | /// in `nt_to_tokenstream\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:207:62 + --> $DIR/unescaped_backticks.rs:208:62 | LL | /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves | ^ @@ -109,7 +109,7 @@ LL | /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_inde | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:215:52 + --> $DIR/unescaped_backticks.rs:216:52 | LL | /// also avoids the need to import `OpenOptions`. | ^ @@ -124,7 +124,7 @@ LL | /// also avoids the need to import `OpenOptions\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:220:46 + --> $DIR/unescaped_backticks.rs:221:46 | LL | /// `HybridBitSet`. Has no effect if `row` does not exist. | ^ @@ -139,7 +139,7 @@ LL | /// `HybridBitSet`. Has no effect if `row\` does not exist. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:246:12 + --> $DIR/unescaped_backticks.rs:247:12 | LL | /// RWU`s can get very large, so it uses a more compact representation. | ^ @@ -154,7 +154,7 @@ LL | /// RWU\`s can get very large, so it uses a more compact representation | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:253:15 + --> $DIR/unescaped_backticks.rs:254:15 | LL | /// in `U2`. | ^ @@ -169,7 +169,7 @@ LL | /// in `U2\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:270:42 + --> $DIR/unescaped_backticks.rs:271:42 | LL | /// because it contains `[type error]`. Yuck! (See issue #29857 for | ^ @@ -184,7 +184,7 @@ LL | /// because it contains `[type error]\`. Yuck! (See issue #29857 for | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:280:53 + --> $DIR/unescaped_backticks.rs:281:53 | LL | /// well as the second instance of `A: AutoTrait`) to suppress | ^ @@ -199,7 +199,7 @@ LL | /// well as the second instance of `A: AutoTrait\`) to suppress | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:290:40 + --> $DIR/unescaped_backticks.rs:291:40 | LL | /// `'a` with `'b` and not `'static`. But it will have to do for | ^ @@ -211,7 +211,7 @@ LL | /// `'a` with `'b` and not `'static\`. But it will have to do for | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:299:54 + --> $DIR/unescaped_backticks.rs:300:54 | LL | /// `None`. Otherwise, it will return `Some(Dispatch)`. | ^ @@ -226,7 +226,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:303:13 + --> $DIR/unescaped_backticks.rs:304:13 | LL | /// or `None` if it isn't. | ^ @@ -238,7 +238,7 @@ LL | /// or `None\` if it isn't. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:307:14 + --> $DIR/unescaped_backticks.rs:308:14 | LL | /// `on_event` should be called. | ^ @@ -253,7 +253,7 @@ LL | /// `on_event\` should be called. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:312:29 + --> $DIR/unescaped_backticks.rs:313:29 | LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max | ^ @@ -268,7 +268,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:322:5 + --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], LL | | @@ -287,7 +287,7 @@ LL | | /// level changes. to this: `None`. Otherwise, it will return `Some(Dispatch)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:322:5 + --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], LL | | @@ -304,7 +304,7 @@ LL | | /// level changes. to this: or `None\` if it isn't. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:322:5 + --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], LL | | @@ -323,7 +323,7 @@ LL | | /// level changes. to this: `on_event\` should be called. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:322:5 + --> $DIR/unescaped_backticks.rs:323:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], LL | | @@ -342,7 +342,7 @@ LL | | /// level changes. to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max error: unescaped backtick - --> $DIR/unescaped_backticks.rs:348:56 + --> $DIR/unescaped_backticks.rs:349:56 | LL | /// instead and use [`CloneCounterObserver::counter`] to increment. | ^ @@ -354,7 +354,7 @@ LL | /// instead and use [`CloneCounterObserver::counter\`] to increment. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:11:5 + --> $DIR/unescaped_backticks.rs:12:5 | LL | /// ` | ^ @@ -366,7 +366,7 @@ LL | /// \` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:18:7 + --> $DIR/unescaped_backticks.rs:19:7 | LL | /// \` | ^ @@ -381,7 +381,7 @@ LL | /// \\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:25:6 + --> $DIR/unescaped_backticks.rs:26:6 | LL | /// [`link1] | ^ @@ -396,7 +396,7 @@ LL | /// [\`link1] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:29:11 + --> $DIR/unescaped_backticks.rs:30:11 | LL | /// [link2`] | ^ @@ -411,7 +411,7 @@ LL | /// [link2\`] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:33:6 + --> $DIR/unescaped_backticks.rs:34:6 | LL | /// [`link_long](link_long) | ^ @@ -426,7 +426,7 @@ LL | /// [\`link_long](link_long) | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:37:6 + --> $DIR/unescaped_backticks.rs:38:6 | LL | /// [`broken-link] | ^ @@ -441,7 +441,7 @@ LL | /// [\`broken-link] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:44:8 + --> $DIR/unescaped_backticks.rs:45:8 | LL | /// <x:`> | ^ @@ -456,7 +456,7 @@ LL | /// <x:\`> | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:54:6 + --> $DIR/unescaped_backticks.rs:55:6 | LL | /// 🦀`🦀 | ^ @@ -475,7 +475,7 @@ LL | /// 🦀\`🦀 | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:58:5 + --> $DIR/unescaped_backticks.rs:59:5 | LL | /// `foo( | ^ @@ -490,7 +490,7 @@ LL | /// \`foo( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:64:14 + --> $DIR/unescaped_backticks.rs:65:14 | LL | /// `foo `bar` | ^ @@ -505,7 +505,7 @@ LL | /// `foo `bar\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:70:5 + --> $DIR/unescaped_backticks.rs:71:5 | LL | /// `foo( | ^ @@ -520,7 +520,7 @@ LL | /// \`foo( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:75:83 + --> $DIR/unescaped_backticks.rs:76:83 | LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`. | ^ @@ -535,7 +535,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:79:51 + --> $DIR/unescaped_backticks.rs:80:51 | LL | /// or even to add a number `n` to 42 (`add(42, b)`)! | ^ @@ -550,7 +550,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:83:83 + --> $DIR/unescaped_backticks.rs:84:83 | LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`. | ^ @@ -565,7 +565,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:87:51 + --> $DIR/unescaped_backticks.rs:88:51 | LL | /// or even to add a number `n` to 42 (`add(42, n)`)! | ^ @@ -580,7 +580,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:91:83 + --> $DIR/unescaped_backticks.rs:92:83 | LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`. | ^ @@ -595,7 +595,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:95:50 + --> $DIR/unescaped_backticks.rs:96:50 | LL | /// or even to add a number `n` to 42 (add(42, n)`)! | ^ @@ -610,7 +610,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:99:74 + --> $DIR/unescaped_backticks.rs:100:74 | LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a). | ^ @@ -625,7 +625,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:103:51 + --> $DIR/unescaped_backticks.rs:104:51 | LL | /// or even to add a number `n` to 42 (`add(42, n)`)! | ^ @@ -640,7 +640,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:107:1 + --> $DIR/unescaped_backticks.rs:108:1 | LL | #[doc = "`"] | ^^^^^^^^^^^^ @@ -651,7 +651,7 @@ LL | #[doc = "`"] to this: \` error: unescaped backtick - --> $DIR/unescaped_backticks.rs:114:1 + --> $DIR/unescaped_backticks.rs:115:1 | LL | #[doc = concat!("\\", "`")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -664,7 +664,7 @@ LL | #[doc = concat!("\\", "`")] to this: \\` error: unescaped backtick - --> $DIR/unescaped_backticks.rs:118:1 + --> $DIR/unescaped_backticks.rs:119:1 | LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -677,7 +677,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:122:1 + --> $DIR/unescaped_backticks.rs:123:1 | LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -690,7 +690,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:126:1 + --> $DIR/unescaped_backticks.rs:127:1 | LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -703,7 +703,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:130:1 + --> $DIR/unescaped_backticks.rs:131:1 | LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -716,7 +716,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a). error: unescaped backtick - --> $DIR/unescaped_backticks.rs:135:5 + --> $DIR/unescaped_backticks.rs:136:5 | LL | /// `foo | ^ @@ -731,7 +731,7 @@ LL | /// \`foo | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:139:7 + --> $DIR/unescaped_backticks.rs:140:7 | LL | /// # `(heading | ^ @@ -746,7 +746,7 @@ LL | /// # \`(heading | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:141:17 + --> $DIR/unescaped_backticks.rs:142:17 | LL | /// ## heading2)` | ^ @@ -761,7 +761,7 @@ LL | /// ## heading2)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:144:11 + --> $DIR/unescaped_backticks.rs:145:11 | LL | /// multi `( | ^ @@ -776,7 +776,7 @@ LL | /// multi \`( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:150:10 + --> $DIR/unescaped_backticks.rs:151:10 | LL | /// para)`(graph | ^ @@ -795,7 +795,7 @@ LL | /// para)\`(graph | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:153:10 + --> $DIR/unescaped_backticks.rs:154:10 | LL | /// para)`(graph2 | ^ @@ -814,7 +814,7 @@ LL | /// para)\`(graph2 | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:156:12 + --> $DIR/unescaped_backticks.rs:157:12 | LL | /// 1. foo)` | ^ @@ -829,7 +829,7 @@ LL | /// 1. foo)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:158:8 + --> $DIR/unescaped_backticks.rs:159:8 | LL | /// 2. `(bar | ^ @@ -844,7 +844,7 @@ LL | /// 2. \`(bar | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:160:11 + --> $DIR/unescaped_backticks.rs:161:11 | LL | /// * baz)` | ^ @@ -859,7 +859,7 @@ LL | /// * baz)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:162:7 + --> $DIR/unescaped_backticks.rs:163:7 | LL | /// * `(quux | ^ @@ -874,7 +874,7 @@ LL | /// * \`(quux | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:165:5 + --> $DIR/unescaped_backticks.rs:166:5 | LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")] | ^ @@ -889,7 +889,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:168:62 + --> $DIR/unescaped_backticks.rs:169:62 | LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]` | ^ @@ -904,7 +904,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:173:7 + --> $DIR/unescaped_backticks.rs:174:7 | LL | /// | `table( | )head` | | ^ @@ -919,7 +919,7 @@ LL | /// | \`table( | )head` | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:173:22 + --> $DIR/unescaped_backticks.rs:174:22 | LL | /// | `table( | )head` | | ^ @@ -934,7 +934,7 @@ LL | /// | `table( | )head\` | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:177:12 + --> $DIR/unescaped_backticks.rs:178:12 | LL | /// | table`( | )`body | | ^ @@ -949,7 +949,7 @@ LL | /// | table\`( | )`body | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:177:18 + --> $DIR/unescaped_backticks.rs:178:18 | LL | /// | table`( | )`body | | ^ diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs index 43cd59ebd09..aabbb4c4c8f 100644 --- a/tests/rustdoc/description.rs +++ b/tests/rustdoc/description.rs @@ -1,4 +1,5 @@ #![crate_name = "foo"] +#![allow(rustdoc::redundant_explicit_links)] //! # Description test crate //! //! This is the contents of the test crate docstring. diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs index 96e21137b2d..c88a7887f11 100644 --- a/tests/rustdoc/intra-doc/basic.rs +++ b/tests/rustdoc/intra-doc/basic.rs @@ -1,3 +1,5 @@ +#![allow(rustdoc::redundant_explicit_links)] + // @has basic/index.html // @has - '//a/@href' 'struct.ThisType.html' // @has - '//a/@title' 'struct basic::ThisType' diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs index fbc9fc6a9bc..359f775f97f 100644 --- a/tests/rustdoc/intra-doc/generic-params.rs +++ b/tests/rustdoc/intra-doc/generic-params.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength #![crate_name = "foo"] +#![allow(rustdoc::redundant_explicit_links)] //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`]. //! Here's a link to [`Iterator<Box<T>>::Item`]. diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs index eb1c7a05e54..b8cd478b4df 100644 --- a/tests/rustdoc/intra-doc/issue-108459.rs +++ b/tests/rustdoc/intra-doc/issue-108459.rs @@ -1,4 +1,5 @@ #![deny(rustdoc::broken_intra_doc_links)] +#![allow(rustdoc::redundant_explicit_links)] pub struct S; pub mod char {} diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs new file mode 100644 index 00000000000..0cfc44cd09d --- /dev/null +++ b/tests/ui/abi/relocation_model_pic.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: -C relocation-model=pic +// ignore-emscripten no pic +// ignore-wasm + +#![feature(cfg_relocation_model)] + +#[cfg(relocation_model = "pic")] +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs new file mode 100644 index 00000000000..7529014ece2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs @@ -0,0 +1,4 @@ +#[cfg(relocation_model = "pic")] //~ ERROR +fn _foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr new file mode 100644 index 00000000000..592768a4203 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(relocation_model)` is experimental and subject to change + --> $DIR/feature-gate-cfg-relocation-model.rs:1:7 + | +LL | #[cfg(relocation_model = "pic")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #114929 <https://github.com/rust-lang/rust/issues/114929> for more information + = help: add `#![feature(cfg_relocation_model)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs new file mode 100644 index 00000000000..0483410662b --- /dev/null +++ b/tests/ui/inline-const/required-const.rs @@ -0,0 +1,13 @@ +// build-fail +// compile-flags: -Zmir-opt-level=3 +#![feature(inline_const)] + +fn foo<T>() { + if false { + const { panic!() } //~ ERROR E0080 + } +} + +fn main() { + foo::<i32>(); +} diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr new file mode 100644 index 00000000000..d6948e7acc0 --- /dev/null +++ b/tests/ui/inline-const/required-const.stderr @@ -0,0 +1,11 @@ +error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed + --> $DIR/required-const.rs:7:17 + | +LL | const { panic!() } + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs index 35003a79ad7..48c1f19e777 100644 --- a/tests/ui/macros/macro-interpolation.rs +++ b/tests/ui/macros/macro-interpolation.rs @@ -1,5 +1,3 @@ -// run-pass - macro_rules! overly_complicated { ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => ({ @@ -21,12 +19,14 @@ macro_rules! qpath { (ty, <$type:ty as $trait:ty>::$name:ident) => { <$type as $trait>::$name + //~^ ERROR expected identifier, found `!` }; } pub fn main() { let _: qpath!(path, <str as ToOwned>::Owned); let _: qpath!(ty, <str as ToOwned>::Owned); + let _: qpath!(ty, <str as !>::Owned); assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); }, Some(8), Some(y), y) == 8) diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr new file mode 100644 index 00000000000..7ef1fcbbce3 --- /dev/null +++ b/tests/ui/macros/macro-interpolation.stderr @@ -0,0 +1,16 @@ +error: expected identifier, found `!` + --> $DIR/macro-interpolation.rs:21:19 + | +LL | <$type as $trait>::$name + | ^^^^^^ expected identifier +... +LL | let _: qpath!(ty, <str as !>::Owned); + | ----------------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation + | + = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs new file mode 100644 index 00000000000..9cc572c23a1 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs @@ -0,0 +1,14 @@ +#![feature(macro_metavar_expr)] + +macro_rules! foo { + ( $( $($t:ident),* );* ) => { ${count(t,)} } + //~^ ERROR `count` followed by a comma must have an associated + //~| ERROR expected expression, found `$` +} + +fn test() { + foo!(a, a; b, b); +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr new file mode 100644 index 00000000000..e9317a5c347 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr @@ -0,0 +1,19 @@ +error: `count` followed by a comma must have an associated index indicating its depth + --> $DIR/issue-111904.rs:4:37 + | +LL | ( $( $($t:ident),* );* ) => { ${count(t,)} } + | ^^^^^ + +error: expected expression, found `$` + --> $DIR/issue-111904.rs:4:35 + | +LL | ( $( $($t:ident),* );* ) => { ${count(t,)} } + | ^ expected expression +... +LL | foo!(a, a; b, b); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 8fafa275b5c..4457b7893d5 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -79,6 +79,14 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | | | pattern doesn't bind `a` +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:12 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `c` + error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:45:22 | @@ -96,12 +104,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:12 + --> $DIR/missing-bindings.rs:45:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; - | ^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `c` + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns --> $DIR/missing-bindings.rs:45:33 @@ -135,14 +143,6 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | | | variable not in all patterns -error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 - | -LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; - | - ^^^^ pattern doesn't bind `c` - | | - | variable not in all patterns - error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:61:29 | @@ -185,6 +185,28 @@ LL | B(b), LL | B(_) | ^^^^ pattern doesn't bind `b` +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:57:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | / V2( +LL | | A( +LL | | A(_, a) | +LL | | B(b), +... | +LL | | +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | V3(c), + | - variable not in all patterns + error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:76:13 | @@ -215,28 +237,6 @@ LL | B(b), LL | V3(c), | ^^^^^ pattern doesn't bind `b` -error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 - | -LL | / V1( -LL | | -LL | | -LL | | A( -... | -LL | | B(Ok(a) | Err(a)) -LL | | ) | - | |_____________^ pattern doesn't bind `c` -LL | / V2( -LL | | A( -LL | | A(_, a) | -LL | | B(b), -... | -LL | | -LL | | ) | - | |_____________^ pattern doesn't bind `c` -LL | V3(c), - | - variable not in all patterns - error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr index 023db303dd0..42b7281d7b0 100644 --- a/tests/ui/resolve/resolve-inconsistent-names.stderr +++ b/tests/ui/resolve/resolve-inconsistent-names.stderr @@ -14,6 +14,15 @@ LL | a | b => {} | | | pattern doesn't bind `b` +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:19:9 + | +LL | (A, B) | (ref B, c) | (c, A) => () + | ^^^^^^ - - variable not in all patterns + | | | + | | variable not in all patterns + | pattern doesn't bind `c` + error[E0408]: variable `A` is not bound in all patterns --> $DIR/resolve-inconsistent-names.rs:19:18 | @@ -37,15 +46,6 @@ LL | (A, B) | (ref B, c) | (c, A) => () | | variable not in all patterns | variable not in all patterns -error[E0408]: variable `c` is not bound in all patterns - --> $DIR/resolve-inconsistent-names.rs:19:9 - | -LL | (A, B) | (ref B, c) | (c, A) => () - | ^^^^^^ - - variable not in all patterns - | | | - | | variable not in all patterns - | pattern doesn't bind `c` - error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|` --> $DIR/resolve-inconsistent-names.rs:19:23 | diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr index 25c35fd5479..81211b20a01 100644 --- a/tests/ui/span/issue-39698.stderr +++ b/tests/ui/span/issue-39698.stderr @@ -1,3 +1,13 @@ +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c` + | | | | + | | | variable not in all patterns + | | pattern doesn't bind `c` + | pattern doesn't bind `c` + error[E0408]: variable `d` is not bound in all patterns --> $DIR/issue-39698.rs:10:37 | @@ -28,16 +38,6 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | variable not in all patterns | pattern doesn't bind `b` -error[E0408]: variable `c` is not bound in all patterns - --> $DIR/issue-39698.rs:10:9 - | -LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } - | ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c` - | | | | - | | | variable not in all patterns - | | pattern doesn't bind `c` - | pattern doesn't bind `c` - error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs new file mode 100644 index 00000000000..b0b9b6bbd20 --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs @@ -0,0 +1,73 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +// A minimization of an ambiguity when using typenum. See +// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55 +// for more details. +trait Id { + type Assoc: ?Sized; +} +impl<T: ?Sized> Id for T { + type Assoc = T; +} + +trait WithAssoc<T: ?Sized> { + type Assoc: ?Sized; +} + + +struct Leaf; +struct Wrapper<U: ?Sized>(U); + +impl<U: ?Sized> WithAssoc<U> for Leaf { + type Assoc = U; +} + +impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul> +where + Ul: WithAssoc<Ur>, +{ + type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc; +} + +fn bound<T: ?Sized, U: ?Sized, V: ?Sized>() +where + T: WithAssoc<U, Assoc = V>, +{ +} + +// normalize self type to `Wrapper<Leaf>` +// This succeeds, HOWEVER, instantiating the query response previously +// incremented the universe index counter. +// equate impl headers: +// <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>> +// <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>> +// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>) +// add where bounds: +// ~> Leaf: WithAssoc<?3t> +// equate with assoc type: +// ?0t +// <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc +// ~> AliasRelate( +// <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc, +// Equate, +// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc, +// ) +// +// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created +// it after incrementing the universe index while normalizing the self type. +// +// evaluate_added_goals_and_make_query_response: +// AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>) +// YES, constrains ?3t to Leaf +// AliasRelate( +// <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc, +// Equate, +// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc, +// ) +// +// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly* +// results in ambiguity. +fn main() { + bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>() +} diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs new file mode 100644 index 00000000000..94d645a9859 --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs @@ -0,0 +1,75 @@ +// compile-flags: -Ztrait-solver=next +// known-bug: trait-system-refactor-initiative#60 + +// Generalizing a projection containing an inference variable +// which cannot be named by the `root_vid` can result in ambiguity. +// +// Because we do not decrement the universe index when exiting a forall, +// this can cause unexpected failures. +// +// See generalize-proj-new-universe-index-1.rs for more details. + +// For this reproduction we need: +// - an inference variable with a lower universe +// - enter a binder to increment the current universe +// - create a new inference variable which is constrained by proving a goal +// - equate a projection containing the new variable with the first variable +// - generalization creates yet another inference variable which is then +// part of an alias-relate, resulting this to fail with ambiguity. +// +// Because we need to enter the binder in-between the creation of the first +// and second inference variable, this is easiest via +// `assemble_candidates_after_normalizing_self_ty` because eagerly call +// `try_evaluate_added_goals` there before creating the inference variables +// for the impl parameters. +trait Id { + type Assoc: ?Sized; +} +impl<T: ?Sized> Id for T { + type Assoc = T; +} + +// By adding an higher ranked bound to the impl we currently +// propagate this bound to the caller, forcing us to create a new +// universe. +trait IdHigherRankedBound { + type Assoc: ?Sized; +} + +impl<T: ?Sized> IdHigherRankedBound for T +where + for<'a> T: 'a, +{ + type Assoc = T; +} + +trait WithAssoc<T: ?Sized> { + type Assoc: ?Sized; +} + + +struct Leaf; +struct Wrapper<U: ?Sized>(U); +struct Rigid; + +impl<U: ?Sized> WithAssoc<U> for Leaf { + type Assoc = U; +} + + +impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid +where + Leaf: WithAssoc<Ur>, +{ + type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc; +} + +fn bound<T: ?Sized, U: ?Sized, V: ?Sized>() +where + T: WithAssoc<U, Assoc = V>, +{ +} + +fn main() { + bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>() +} diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr new file mode 100644 index 00000000000..9a8060133b8 --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/generalize-proj-new-universe-index-2.rs:74:5 + | +LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr index d48d9b89d1d..b612005fcb0 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr @@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` --> $DIR/type-checking-test-1.rs:19:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous - | ^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let _ = &x as &dyn Bar<_>; // Ambiguous - | + - -error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied - --> $DIR/type-checking-test-1.rs:19:13 - | -LL | let _ = x as &dyn Bar<_>; // Ambiguous - | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` - | - = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>` + | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0605. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs index 7c7beec0809..afea8521e87 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) { fn test_unknown_version(x: &dyn Foo) { let _ = x as &dyn Bar<_>; // Ambiguous //~^ ERROR non-primitive cast - //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied } fn test_infer_version(x: &dyn Foo) { diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs index 36b11dffdb1..b024b27750b 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo<u32>) { fn test_specific3(x: &dyn Foo<i32>) { let _ = x as &dyn Bar<u32>; // Error //~^ ERROR non-primitive cast - //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied } fn test_infer_arg(x: &dyn Foo<u32>) { let a = x as &dyn Bar<_>; // Ambiguous //~^ ERROR non-primitive cast - //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied let _ = a.bar(); } diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr index 856303ef4dd..3e59b9d3363 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>` --> $DIR/type-checking-test-2.rs:19:13 | LL | let _ = x as &dyn Bar<u32>; // Error - | ^^^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let _ = &x as &dyn Bar<u32>; // Error - | + - -error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied - --> $DIR/type-checking-test-2.rs:19:13 - | -LL | let _ = x as &dyn Bar<u32>; // Error - | ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>` - | - = note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>` + | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>` - --> $DIR/type-checking-test-2.rs:25:13 + --> $DIR/type-checking-test-2.rs:24:13 | LL | let a = x as &dyn Bar<_>; // Ambiguous - | ^^^^^^^^^^^^^^^^ invalid cast - | -help: consider borrowing the value - | -LL | let a = &x as &dyn Bar<_>; // Ambiguous - | + - -error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied - --> $DIR/type-checking-test-2.rs:25:13 - | -LL | let a = x as &dyn Bar<_>; // Ambiguous - | ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>` - | - = note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>` + | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0605. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0605`. diff --git a/triagebot.toml b/triagebot.toml index 2c71b650f68..a06195cc334 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -489,7 +489,7 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789", "oli-obk"] +users_on_vacation = ["jyn514", "clubby789", "oli-obk"] [assign.adhoc_groups] compiler-team = [ |
