about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--config.toml.example4
-rw-r--r--src/bootstrap/builder.rs9
-rw-r--r--src/bootstrap/config.rs6
-rw-r--r--src/bootstrap/flags.rs14
-rw-r--r--src/librustc_ast_passes/node_count.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs25
-rw-r--r--src/librustc_middle/middle/region.rs4
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs70
-rw-r--r--src/librustc_target/spec/mipsel_sony_psp.rs43
-rw-r--r--src/librustc_target/spec/mipsel_sony_psp_linker_script.ld34
-rw-r--r--src/librustc_target/spec/mod.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs7
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs66
m---------src/stdarch0
-rw-r--r--src/test/rustdoc/intra-link-trait-impl.rs35
-rw-r--r--triagebot.toml2
16 files changed, 279 insertions, 51 deletions
diff --git a/config.toml.example b/config.toml.example
index 5447434143c..ffe907c9da9 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -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
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 0a5f07c6895..4bc81a7b42d 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -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"))
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 13f88c185ae..771f952abc0 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -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) {
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index fb380af0a47..646b9e05d99 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -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")),
diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs
index 3cf562b927e..34db59b1b45 100644
--- a/src/librustc_ast_passes/node_count.rs
+++ b/src/librustc_ast_passes/node_count.rs
@@ -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::*;
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index d8b38cf3370..a54160cdd71 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -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 {
diff --git a/src/librustc_middle/middle/region.rs b/src/librustc_middle/middle/region.rs
index c3eeea7662b..f02d8fe8ad6 100644
--- a/src/librustc_middle/middle/region.rs
+++ b/src/librustc_middle/middle/region.rs
@@ -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;
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 534fe172bef..3dd715f9e3d 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -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.
diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs
new file mode 100644
index 00000000000..0c74454d0c5
--- /dev/null
+++ b/src/librustc_target/spec/mipsel_sony_psp.rs
@@ -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()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld
new file mode 100644
index 00000000000..1bd436d6f94
--- /dev/null
+++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld
@@ -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.*)) }
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 477161dc658..c7b2023ddca 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -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);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 956e09ec52b..79dde84b8b1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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);
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index fbdb538cd87..a3ef350a048 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -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);
diff --git a/src/stdarch b/src/stdarch
-Subproject d10eefc62284c40c5a95a2eed19fc1f414a5364
+Subproject ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1
diff --git a/src/test/rustdoc/intra-link-trait-impl.rs b/src/test/rustdoc/intra-link-trait-impl.rs
new file mode 100644
index 00000000000..fab8406d525
--- /dev/null
+++ b/src/test/rustdoc/intra-link-trait-impl.rs
@@ -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();
+}
diff --git a/triagebot.toml b/triagebot.toml
index 56d29994a8d..2210a8ff8e6 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -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