Auto merge of #72222 - Dylan-DPC:rollup-vaw44dg, r=Dylan-DPC

Rollup of 7 pull requests

Successful merges:

 - #71809 (Use `LocalDefId` in `DumpVisitor::nest_tables`)
 - #72062 (Add built in PSP target)
 - #72146 (Provide separate option for std debug asserts)
 - #72172 (Forbid stage arguments to check)
 - #72173 (Make intra links work inside trait impl block)
 - #72200 (Add prioritize_on attribute to triagebot)
 - #72214 (Minor fixes to comments)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-05-15 02:56:38 +00:00
commit 027149919e
16 changed files with 280 additions and 52 deletions

View file

@ -314,6 +314,10 @@
# library.
#debug-assertions = false
# Whether or not debug assertions are enabled for the standard library.
# Overrides the `debug-assertions` option, if defined.
#debug-assertions-std = false
# Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`.
# `0` - no debug info
# `1` - line tables only

View file

@ -915,7 +915,14 @@ impl<'a> Builder<'a> {
.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
.env("RUSTC_REAL", self.rustc(compiler))
.env("RUSTC_STAGE", stage.to_string())
.env("RUSTC_DEBUG_ASSERTIONS", self.config.rust_debug_assertions.to_string())
.env(
"RUSTC_DEBUG_ASSERTIONS",
if mode == Mode::Std {
self.config.rust_debug_assertions_std.to_string()
} else {
self.config.rust_debug_assertions.to_string()
},
)
.env("RUSTC_SYSROOT", &sysroot)
.env("RUSTC_LIBDIR", &libdir)
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))

View file

@ -97,6 +97,7 @@ pub struct Config {
pub rust_codegen_units: Option<u32>,
pub rust_codegen_units_std: Option<u32>,
pub rust_debug_assertions: bool,
pub rust_debug_assertions_std: bool,
pub rust_debuginfo_level_rustc: u32,
pub rust_debuginfo_level_std: u32,
pub rust_debuginfo_level_tools: u32,
@ -314,6 +315,7 @@ struct Rust {
codegen_units: Option<u32>,
codegen_units_std: Option<u32>,
debug_assertions: Option<bool>,
debug_assertions_std: Option<bool>,
debuginfo_level: Option<u32>,
debuginfo_level_rustc: Option<u32>,
debuginfo_level_std: Option<u32>,
@ -518,6 +520,7 @@ impl Config {
let mut llvm_assertions = None;
let mut debug = None;
let mut debug_assertions = None;
let mut debug_assertions_std = None;
let mut debuginfo_level = None;
let mut debuginfo_level_rustc = None;
let mut debuginfo_level_std = None;
@ -560,6 +563,7 @@ impl Config {
if let Some(ref rust) = toml.rust {
debug = rust.debug;
debug_assertions = rust.debug_assertions;
debug_assertions_std = rust.debug_assertions_std;
debuginfo_level = rust.debuginfo_level;
debuginfo_level_rustc = rust.debuginfo_level_rustc;
debuginfo_level_std = rust.debuginfo_level_std;
@ -658,6 +662,8 @@ impl Config {
let default = debug == Some(true);
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
config.rust_debug_assertions_std =
debug_assertions_std.unwrap_or(config.rust_debug_assertions);
let with_defaults = |debuginfo_level_specific: Option<u32>| {
debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {

View file

@ -503,6 +503,20 @@ Arguments:
}
};
if let Subcommand::Check { .. } = &cmd {
if matches.opt_str("stage").is_some() {
println!("{}", "--stage not supported for x.py check, always treated as stage 0");
process::exit(1);
}
if matches.opt_str("keep-stage").is_some() {
println!(
"{}",
"--keep-stage not supported for x.py check, only one stage available"
);
process::exit(1);
}
}
Flags {
verbose: matches.opt_count("verbose"),
stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")),

View file

@ -1,4 +1,4 @@
// Simply gives a rought count of the number of nodes in an AST.
// Simply gives a rough count of the number of nodes in an AST.
use rustc_ast::ast::*;
use rustc_ast::visit::*;

View file

@ -1179,6 +1179,28 @@ fn add_pre_link_args(
cmd.args(&sess.opts.debugging_opts.pre_link_args);
}
/// Add a link script embedded in the target, if applicable.
fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
match (crate_type, &sess.target.target.options.link_script) {
(CrateType::Cdylib | CrateType::Executable, Some(script)) => {
if !sess.target.target.options.linker_is_gnu {
sess.fatal("can only use link script when linking with GNU-like linker");
}
let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-");
let path = tmpdir.join(file_name);
if let Err(e) = fs::write(&path, script) {
sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e));
}
cmd.arg("--script");
cmd.arg(path);
}
_ => {}
}
}
/// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes.
/// FIXME: Determine where exactly these args need to be inserted.
fn add_user_defined_link_args(
@ -1421,6 +1443,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
add_pre_link_args(cmd, sess, flavor, crate_type);
// NO-OPT-OUT
add_link_script(cmd, sess, tmpdir, crate_type);
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
if sess.target.target.options.is_like_fuchsia {
let prefix = match sess.opts.debugging_opts.sanitizer {

View file

@ -4,7 +4,7 @@
//! For more information about how MIR-based region-checking works,
//! see the [rustc dev guide].
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/borrowck.html
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::ty::{self, DefIdTree, TyCtxt};
@ -181,7 +181,7 @@ impl Scope {
// `blk`; reuse span of `blk` and shift `lo`
// forward to end of indexed statement.
//
// (This is the special case aluded to in the
// (This is the special case alluded to in the
// doc-comment for this method)
let stmt_span = blk.stmts[first_statement_index.index()].span;

View file

@ -21,7 +21,7 @@ use rustc_ast::walk_list;
use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to_string};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind as HirDefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::Input;
@ -104,12 +104,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
self.dumper.analysis()
}
fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
fn nest_tables<F>(&mut self, item_def_id: LocalDefId, f: F)
where
F: FnOnce(&mut Self),
{
let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
let tables = if self.tcx.has_typeck_tables(item_def_id) {
self.tcx.typeck_tables_of(item_def_id)
} else {
@ -272,8 +270,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
) {
debug!("process_method: {}:{}", id, ident);
let hir_id = self.tcx.hir().node_id_to_hir_id(id);
self.nest_tables(id, |v| {
let map = &self.tcx.hir();
let hir_id = map.node_id_to_hir_id(id);
self.nest_tables(map.local_def_id(hir_id), |v| {
if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
v.process_formals(&sig.decl.inputs, &method_data.qualname);
v.process_generic_params(&generics, &method_data.qualname, id);
@ -296,7 +295,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
// start walking from the newly-created definition.
match sig.header.asyncness {
ast::Async::Yes { return_impl_trait_id, .. } => {
v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
let hir_id = map.node_id_to_hir_id(return_impl_trait_id);
v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty))
}
_ => v.visit_ty(ret_ty),
}
@ -364,8 +364,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
ty_params: &'l ast::Generics,
body: Option<&'l ast::Block>,
) {
let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
self.nest_tables(item.id, |v| {
let map = &self.tcx.hir();
let hir_id = map.node_id_to_hir_id(item.id);
self.nest_tables(map.local_def_id(hir_id), |v| {
if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
down_cast_data!(fn_data, DefData, item.span);
v.process_formals(&decl.inputs, &fn_data.qualname);
@ -389,7 +390,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
// start walking from the newly-created definition.
match header.asyncness {
ast::Async::Yes { return_impl_trait_id, .. } => {
v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty))
let hir_id = map.node_id_to_hir_id(return_impl_trait_id);
v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty))
}
_ => v.visit_ty(ret_ty),
}
@ -407,7 +409,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
expr: Option<&'l ast::Expr>,
) {
let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
self.nest_tables(item.id, |v| {
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
if let Some(var_data) = v.save_ctxt.get_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data);
@ -427,15 +429,13 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
vis: ast::Visibility,
attrs: &'l [Attribute],
) {
let qualname = format!(
"::{}",
self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id).to_def_id())
);
let hir_id = self.tcx.hir().node_id_to_hir_id(id);
let qualname =
format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id()));
if !self.span.filter_generated(ident.span) {
let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
let span = self.span_from_span(ident.span);
let hir_id = self.tcx.hir().node_id_to_hir_id(id);
self.dumper.dump_def(
&access_from_vis!(self.save_ctxt, vis, hir_id),
@ -457,7 +457,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
// walk type and init value
self.nest_tables(id, |v| {
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
v.visit_ty(typ);
if let Some(expr) = expr {
v.visit_expr(expr);
@ -474,10 +474,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
) {
debug!("process_struct {:?} {:?}", item, item.span);
let name = item.ident.to_string();
let qualname = format!(
"::{}",
self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id())
);
let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
let qualname =
format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id()));
let kind = match item.kind {
ast::ItemKind::Struct(_, _) => DefKind::Struct,
@ -509,7 +508,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
self.dumper.dump_def(
&access_from!(self.save_ctxt, item, hir_id),
Def {
@ -529,7 +527,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
);
}
self.nest_tables(item.id, |v| {
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
for field in def.fields() {
v.process_struct_field_def(field, item.id);
v.visit_ty(&field.ty);
@ -669,14 +667,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
let map = &self.tcx.hir();
self.nest_tables(item.id, |v| {
let hir_id = map.node_id_to_hir_id(item.id);
self.nest_tables(map.local_def_id(hir_id), |v| {
v.visit_ty(&typ);
if let &Some(ref trait_ref) = trait_ref {
v.process_path(trait_ref.ref_id, &trait_ref.path);
}
v.process_generic_params(generics, "", item.id);
for impl_item in impl_items {
v.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id).to_def_id());
v.process_impl_item(impl_item, map.local_def_id(hir_id).to_def_id());
}
});
}
@ -1411,7 +1410,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
}
ast::TyKind::Array(ref element, ref length) => {
self.visit_ty(element);
self.nest_tables(length.id, |v| v.visit_expr(&length.value));
let hir_id = self.tcx.hir().node_id_to_hir_id(length.id);
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
v.visit_expr(&length.value)
});
}
ast::TyKind::ImplTrait(id, ref bounds) => {
// FIXME: As of writing, the opaque type lowering introduces
@ -1423,7 +1425,13 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
// bounds...
// This will panic if called on return type `impl Trait`, which
// we guard against in `process_fn`.
self.nest_tables(id, |v| v.process_bounds(bounds));
// FIXME(#71104) Should really be using just `node_id_to_hir_id` but
// some `NodeId` do not seem to have a corresponding HirId.
if let Some(hir_id) = self.tcx.hir().opt_node_id_to_hir_id(id) {
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
v.process_bounds(bounds)
});
}
}
_ => visit::walk_ty(self, t),
}
@ -1471,7 +1479,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
}
// walk the body
self.nest_tables(ex.id, |v| {
let hir_id = self.tcx.hir().node_id_to_hir_id(ex.id);
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
v.process_formals(&decl.inputs, &id);
v.visit_expr(body)
});
@ -1488,7 +1497,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
}
ast::ExprKind::Repeat(ref element, ref count) => {
self.visit_expr(element);
self.nest_tables(count.id, |v| v.visit_expr(&count.value));
let hir_id = self.tcx.hir().node_id_to_hir_id(count.id);
self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
v.visit_expr(&count.value)
});
}
// In particular, we take this branch for call and path expressions,
// where we'll index the idents involved just by continuing to walk.

View file

@ -0,0 +1,43 @@
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
use crate::spec::{Target, TargetOptions, TargetResult};
// The PSP has custom linker requirements.
const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
pub fn target() -> TargetResult {
let mut pre_link_args = LinkArgs::new();
pre_link_args.insert(
LinkerFlavor::Lld(LldFlavor::Ld),
vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()],
);
Ok(Target {
llvm_target: "mipsel-sony-psp".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
arch: "mips".to_string(),
target_os: "psp".to_string(),
target_env: "".to_string(),
target_vendor: "sony".to_string(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
options: TargetOptions {
cpu: "mips2".to_string(),
executables: true,
linker: Some("rust-lld".to_owned()),
linker_is_gnu: true,
relocation_model: RelocModel::Static,
// PSP FPU only supports single precision floats.
features: "+single-float".to_string(),
// PSP does not support trap-on-condition instructions.
llvm_args: vec!["-mno-check-zero-division".to_string()],
pre_link_args,
link_script: Some(LINKER_SCRIPT.to_string()),
..Default::default()
},
})
}

View file

@ -0,0 +1,34 @@
ENTRY(module_start)
SECTIONS
{
/* PRX format requires text to begin at 0 */
.text 0 : { *(.text .text.*) }
/* Sort stubs for convenient ordering */
.sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
/* Keep these sections around, even though they may appear unused to the linker */
.lib.ent.top : { KEEP(*(.lib.ent.top)) }
.lib.ent : { KEEP(*(.lib.ent)) }
.lib.ent.btm : { KEEP(*(.lib.ent.btm)) }
.lib.stub.top : { KEEP(*(.lib.stub.top)) }
.lib.stub : { KEEP(*(.lib.stub)) }
.lib.stub.btm : { KEEP(*(.lib.stub.btm)) }
.eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) }
/* Add symbols for LLVM's libunwind */
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
.eh_frame :
{
__eh_frame_start = .;
KEEP(*(.eh_frame))
__eh_frame_end = .;
}
/* These are explicitly listed to avoid being merged into .rodata */
.rodata.sceResident : { *(.rodata.sceResident) }
.rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
/* Sort NIDs for convenient ordering */
.rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) }
}

View file

@ -582,6 +582,8 @@ supported_targets! {
("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
("mipsel-sony-psp", mipsel_sony_psp),
}
/// Everything `rustc` knows about how to compile for a specific target.
@ -666,6 +668,10 @@ pub struct TargetOptions {
/// Linker arguments that are unconditionally passed *after* any
/// user-defined libraries.
pub post_link_args: LinkArgs,
/// Optional link script applied to `dylib` and `executable` crate types.
/// This is a string containing the script, not a path. Can only be applied
/// to linkers where `linker_is_gnu` is true.
pub link_script: Option<String>,
/// Environment variables to be set for the linker invocation.
pub link_env: Vec<(String, String)>,
@ -899,6 +905,7 @@ impl Default for TargetOptions {
pre_link_args: LinkArgs::new(),
pre_link_args_crt: LinkArgs::new(),
post_link_args: LinkArgs::new(),
link_script: None,
asm_args: Vec::new(),
cpu: "generic".to_string(),
features: String::new(),
@ -1249,6 +1256,7 @@ impl Target {
key!(post_link_objects, list);
key!(post_link_objects_crt, list);
key!(post_link_args, link_args);
key!(link_script, optional);
key!(link_env, env);
key!(link_env_remove, list);
key!(asm_args, list);
@ -1479,6 +1487,7 @@ impl ToJson for Target {
target_option_val!(post_link_objects);
target_option_val!(post_link_objects_crt);
target_option_val!(link_args - post_link_args);
target_option_val!(link_script);
target_option_val!(env - link_env);
target_option_val!(link_env_remove);
target_option_val!(asm_args);

View file

@ -831,13 +831,6 @@ fn primary_body_of(
}
fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// FIXME(#71104) some `LocalDefId` do not seem to have a corresponding `HirId`.
if let Some(def_id) = def_id.as_local() {
if tcx.hir().opt_local_def_id_to_hir_id(def_id).is_none() {
return false;
}
}
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);

View file

@ -12,7 +12,8 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty;
use rustc_resolve::ParentScope;
use rustc_session::lint;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::symbol::Ident;
use rustc_span::symbol::Symbol;
use rustc_span::DUMMY_SP;
use std::ops::Range;
@ -130,6 +131,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
current_item: &Option<String>,
parent_id: Option<hir::HirId>,
extra_fragment: &Option<String>,
item_opt: Option<&Item>,
) -> Result<(Res, Option<String>), ErrorKind> {
let cx = self.cx;
@ -230,16 +232,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias,
did,
) => {
let item = cx
.tcx
.inherent_impls(did)
.iter()
.flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
.find(|item| item.ident.name == item_name);
// We need item's parent to know if it's
// trait impl or struct/enum/etc impl
let item_parent = item_opt
.and_then(|item| self.cx.as_local_hir_id(item.def_id))
.and_then(|item_hir| {
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
self.cx.tcx.hir().find(parent_hir)
});
let item = match item_parent {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. },
..
})) => {
// trait impl
cx.tcx
.associated_item_def_ids(self_ty.hir_id.owner)
.iter()
.map(|child| {
let associated_item = cx.tcx.associated_item(*child);
associated_item
})
.find(|child| child.ident.name == item_name)
}
_ => {
// struct/enum/etc. impl
cx.tcx
.inherent_impls(did)
.iter()
.flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
.find(|item| item.ident.name == item_name)
}
};
if let Some(item) = item {
let out = match item.kind {
ty::AssocKind::Fn if ns == ValueNS => "method",
ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
ty::AssocKind::Type if ns == ValueNS => "associatedtype",
_ => return self.variant_field(path_str, current_item, module_id),
};
if extra_fragment.is_some() {
@ -484,8 +514,14 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
match kind {
Some(ns @ ValueNS) => {
match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
{
match self.resolve(
path_str,
ns,
&current_item,
base_node,
&extra_fragment,
None,
) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
resolution_failure(cx, &item, path_str, &dox, link_range);
@ -501,8 +537,14 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}
}
Some(ns @ TypeNS) => {
match self.resolve(path_str, ns, &current_item, base_node, &extra_fragment)
{
match self.resolve(
path_str,
ns,
&current_item,
base_node,
&extra_fragment,
None,
) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
resolution_failure(cx, &item, path_str, &dox, link_range);
@ -526,6 +568,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
&current_item,
base_node,
&extra_fragment,
None,
) {
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
@ -539,6 +582,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
&current_item,
base_node,
&extra_fragment,
Some(&item),
) {
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);

@ -1 +1 @@
Subproject commit d10eefc62284c40c5a95a2eed19fc1f414a5364d
Subproject commit ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1b

View file

@ -0,0 +1,35 @@
#![crate_name = "foo"]
// ignore-tidy-linelength
pub struct MyStruct;
impl MyTrait for MyStruct {
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType'
/// [`AssoType`]
///
/// [`AssoType`]: MyStruct::AssoType
type AssoType = u32;
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST'
/// [`ASSO_CONST`]
///
/// [`ASSO_CONST`]: MyStruct::ASSO_CONST
const ASSO_CONST: i32 = 10;
// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.trait_fn'
/// [`trait_fn`]
///
/// [`trait_fn`]: MyStruct::trait_fn
fn trait_fn() { }
}
pub trait MyTrait {
type AssoType;
const ASSO_CONST: i32 = 1;
fn trait_fn();
}

View file

@ -36,4 +36,6 @@ label = "ICEBreaker-Cleanup-Crew"
[prioritize]
label = "I-prioritize"
prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]
priority_labels = "P-*"
zulip_stream = 227806