about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-02 16:26:10 +0000
committerbors <bors@rust-lang.org>2019-04-02 16:26:10 +0000
commit428943cc290e64187e0698f41853ef316c0a7d03 (patch)
tree16bf85f0b8cecaefe14b06f33a4251ad90dd11d9
parente008e4fde837313d4a72da603ef492a721afc998 (diff)
parent21e2e98b8ce445141eb91b5d93ecfc416b5e279a (diff)
downloadrust-428943cc290e64187e0698f41853ef316c0a7d03.tar.gz
rust-428943cc290e64187e0698f41853ef316c0a7d03.zip
Auto merge of #59636 - Centril:rollup, r=Centril
Rollup of 4 pull requests

Successful merges:

 - #59166 (resolve: collect trait aliases along with traits)
 - #59341 (Fix custom relative libdir)
 - #59446 (Fix stack overflow when generating debuginfo for 'recursive' type)
 - #59529 (Added documentation on the remainder (Rem) operator for floating points.)

Failed merges:

r? @ghost
-rw-r--r--src/bootstrap/builder.rs23
-rw-r--r--src/bootstrap/compile.rs8
-rw-r--r--src/bootstrap/dist.rs15
-rw-r--r--src/bootstrap/lib.rs1
-rw-r--r--src/libcore/ops/arith.rs15
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs66
-rw-r--r--src/librustc_codegen_llvm/debuginfo/type_names.rs62
-rw-r--r--src/librustc_resolve/lib.rs59
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs46
-rw-r--r--src/librustc_typeck/check/method/suggest.rs13
-rw-r--r--src/test/codegen/fn-impl-trait-self.rs15
-rw-r--r--src/test/run-pass/issues/issue-58463.rs8
-rw-r--r--src/test/run-pass/traits/auxiliary/trait_alias.rs13
-rw-r--r--src/test/run-pass/traits/trait-alias-import-cross-crate.rs14
-rw-r--r--src/test/run-pass/traits/trait-alias-import.rs38
-rw-r--r--src/test/ui/traits/trait-alias-ambiguous.rs24
-rw-r--r--src/test/ui/traits/trait-alias-ambiguous.stderr20
18 files changed, 377 insertions, 65 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8d3c8fc435c..522466314d6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -634,7 +634,28 @@ impl<'a> Builder<'a> {
         if compiler.is_snapshot(self) {
             self.rustc_snapshot_libdir()
         } else {
-            self.sysroot(compiler).join(libdir(&compiler.host))
+            match self.config.libdir_relative() {
+                Some(relative_libdir) if compiler.stage >= 1
+                    => self.sysroot(compiler).join(relative_libdir),
+                _ => self.sysroot(compiler).join(libdir(&compiler.host))
+            }
+        }
+    }
+
+    /// Returns the compiler's relative libdir where it stores the dynamic libraries that
+    /// it itself links against.
+    ///
+    /// For example this returns `lib` on Unix and `bin` on
+    /// Windows.
+    pub fn libdir_relative(&self, compiler: Compiler) -> &Path {
+        if compiler.is_snapshot(self) {
+            libdir(&self.config.build).as_ref()
+        } else {
+            match self.config.libdir_relative() {
+                Some(relative_libdir) if compiler.stage >= 1
+                    => relative_libdir,
+                _ => libdir(&compiler.host).as_ref()
+            }
         }
     }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 237f5c0ea2f..08316b71ea8 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -20,7 +20,7 @@ use filetime::FileTime;
 use serde_json;
 
 use crate::dist;
-use crate::util::{exe, libdir, is_dylib};
+use crate::util::{exe, is_dylib};
 use crate::{Compiler, Mode, GitRepo};
 use crate::native;
 
@@ -1005,13 +1005,13 @@ impl Step for Assemble {
 
         // Link in all dylibs to the libdir
         let sysroot = builder.sysroot(target_compiler);
-        let sysroot_libdir = sysroot.join(libdir(&*host));
-        t!(fs::create_dir_all(&sysroot_libdir));
+        let rustc_libdir = builder.rustc_libdir(target_compiler);
+        t!(fs::create_dir_all(&rustc_libdir));
         let src_libdir = builder.sysroot_libdir(build_compiler, host);
         for f in builder.read_dir(&src_libdir) {
             let filename = f.file_name().into_string().unwrap();
             if is_dylib(&filename) {
-                builder.copy(&f.path(), &sysroot_libdir.join(&filename));
+                builder.copy(&f.path(), &rustc_libdir.join(&filename));
             }
         }
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index d982330a616..a4d924d64ee 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -18,7 +18,7 @@ use build_helper::output;
 
 use crate::{Compiler, Mode, LLVM_TOOLS};
 use crate::channel;
-use crate::util::{libdir, is_dylib, exe};
+use crate::util::{is_dylib, exe};
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::compile;
 use crate::tool::{self, Tool};
@@ -473,7 +473,7 @@ impl Step for Rustc {
         fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
             let host = compiler.host;
             let src = builder.sysroot(compiler);
-            let libdir = libdir(&host);
+            let libdir = builder.rustc_libdir(compiler);
 
             // Copy rustc/rustdoc binaries
             t!(fs::create_dir_all(image.join("bin")));
@@ -481,13 +481,15 @@ impl Step for Rustc {
 
             builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
 
+            let libdir_relative = builder.libdir_relative(compiler);
+
             // Copy runtime DLLs needed by the compiler
-            if libdir != "bin" {
-                for entry in builder.read_dir(&src.join(libdir)) {
+            if libdir_relative.to_str() != Some("bin") {
+                for entry in builder.read_dir(&libdir) {
                     let name = entry.file_name();
                     if let Some(s) = name.to_str() {
                         if is_dylib(s) {
-                            builder.install(&entry.path(), &image.join(libdir), 0o644);
+                            builder.install(&entry.path(), &image.join(&libdir_relative), 0o644);
                         }
                     }
                 }
@@ -516,7 +518,8 @@ impl Step for Rustc {
                     .join("bin")
                     .join(&exe);
                 // for the rationale about this rename check `compile::copy_lld_to_sysroot`
-                let dst = image.join("lib/rustlib")
+                let dst = image.join(libdir_relative)
+                    .join("rustlib")
                     .join(&*host)
                     .join("bin")
                     .join(&exe);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2394ae7fb79..47ac04baf6d 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1275,6 +1275,7 @@ impl Build {
     fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
         if self.config.dry_run { return; }
         let dst = dstdir.join(src.file_name().unwrap());
+        self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
         t!(fs::create_dir_all(dstdir));
         drop(fs::remove_file(&dst));
         {
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index 28c9ff94dee..0688a606591 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -537,6 +537,21 @@ rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
 macro_rules! rem_impl_float {
     ($($t:ty)*) => ($(
+
+        /// The remainder from the division of two floats.
+        ///
+        /// The remainder has the same sign as the dividend and is computed as:
+        /// `x - (x / y).trunc() * y`.
+        ///
+        /// # Examples
+        /// ```
+        /// let x: f32 = 50.50;
+        /// let y: f32 = 8.125;
+        /// let remainder = x - (x / y).trunc() * y;
+        ///
+        /// // The answer to both operations is 1.75
+        /// assert_eq!(x % y, remainder);
+        /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Rem for $t {
             type Output = $t;
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index e549b120da9..94d520ec78c 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -117,6 +117,32 @@ impl TypeMap<'ll, 'tcx> {
         }
     }
 
+    // Removes a Ty to metadata mapping
+    // This is useful when computing the metadata for a potentially
+    // recursive type (e.g. a function ptr of the form:
+    //
+    // fn foo() -> impl Copy { foo }
+    //
+    // This kind of type cannot be properly represented
+    // via LLVM debuginfo. As a workaround,
+    // we register a temporary Ty to metadata mapping
+    // for the function before we compute its actual metadata.
+    // If the metadata computation ends up recursing back to the
+    // original function, it will use the temporary mapping
+    // for the inner self-reference, preventing us from
+    // recursing forever.
+    //
+    // This function is used to remove the temporary metadata
+    // mapping after we've computed the actual metadata
+    fn remove_type(
+        &mut self,
+        type_: Ty<'tcx>,
+    ) {
+        if self.type_to_metadata.remove(type_).is_none() {
+            bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
+        }
+    }
+
     // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
     // fail if the mapping already exists.
     fn register_unique_id_with_metadata(
@@ -608,10 +634,7 @@ pub fn type_metadata(
             }
         }
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let fn_metadata = subroutine_type_metadata(cx,
-                                                       unique_type_id,
-                                                       t.fn_sig(cx.tcx),
-                                                       usage_site_span).metadata;
+
             if let Some(metadata) = debug_context(cx).type_map
                .borrow()
                .find_metadata_for_unique_id(unique_type_id)
@@ -619,6 +642,41 @@ pub fn type_metadata(
                 return metadata;
             }
 
+            // It's possible to create a self-referential
+            // type in Rust by using 'impl trait':
+            //
+            // fn foo() -> impl Copy { foo }
+            //
+            // See TypeMap::remove_type for more detals
+            // about the workaround
+
+            let temp_type = {
+                unsafe {
+                    // The choice of type here is pretty arbitrary -
+                    // anything reading the debuginfo for a recursive
+                    // type is going to see *somthing* weird - the only
+                    // question is what exactly it will see
+                    let (size, align) = cx.size_and_align_of(t);
+                    llvm::LLVMRustDIBuilderCreateBasicType(
+                        DIB(cx),
+                        SmallCStr::new("<recur_type>").as_ptr(),
+                        size.bits(),
+                        align.bits() as u32,
+                        DW_ATE_unsigned)
+                }
+            };
+
+            let type_map = &debug_context(cx).type_map;
+            type_map.borrow_mut().register_type_with_metadata(t, temp_type);
+
+            let fn_metadata = subroutine_type_metadata(cx,
+                                                       unique_type_id,
+                                                       t.fn_sig(cx.tcx),
+                                                       usage_site_span).metadata;
+
+            type_map.borrow_mut().remove_type(t);
+
+
             // This is actually a function pointer, so wrap it in pointer DI
             MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
 
diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs
index 8b218ab39d9..eff7cd1bc8a 100644
--- a/src/librustc_codegen_llvm/debuginfo/type_names.rs
+++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs
@@ -5,6 +5,7 @@ use rustc::hir::def_id::DefId;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty};
 use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::fx::FxHashSet;
 
 use rustc::hir;
 
@@ -17,7 +18,8 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                              qualified: bool)
                                              -> String {
     let mut result = String::with_capacity(64);
-    push_debuginfo_type_name(cx, t, qualified, &mut result);
+    let mut visited = FxHashSet::default();
+    push_debuginfo_type_name(cx, t, qualified, &mut result, &mut visited);
     result
 }
 
@@ -26,7 +28,9 @@ pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                           t: Ty<'tcx>,
                                           qualified: bool,
-                                          output: &mut String) {
+                                          output: &mut String,
+                                          visited: &mut FxHashSet<Ty<'tcx>>) {
+
     // When targeting MSVC, emit C++ style type names for compatibility with
     // .natvis visualizers (and perhaps other existing native debuggers?)
     let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
@@ -42,12 +46,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
         ty::Adt(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
-            push_type_params(cx, substs, output);
+            push_type_params(cx, substs, output, visited);
         },
         ty::Tuple(component_types) => {
             output.push('(');
             for &component_type in component_types {
-                push_debuginfo_type_name(cx, component_type, true, output);
+                push_debuginfo_type_name(cx, component_type, true, output, visited);
                 output.push_str(", ");
             }
             if !component_types.is_empty() {
@@ -65,7 +69,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 hir::MutMutable => output.push_str("mut "),
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('*');
@@ -79,7 +83,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push_str("mut ");
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('*');
@@ -87,7 +91,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         },
         ty::Array(inner_type, len) => {
             output.push('[');
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
             output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
             output.push(']');
         },
@@ -98,7 +102,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 output.push('[');
             }
 
-            push_debuginfo_type_name(cx, inner_type, true, output);
+            push_debuginfo_type_name(cx, inner_type, true, output, visited);
 
             if cpp_like_names {
                 output.push('>');
@@ -113,12 +117,31 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     &principal,
                 );
                 push_item_name(cx, principal.def_id, false, output);
-                push_type_params(cx, principal.substs, output);
+                push_type_params(cx, principal.substs, output, visited);
             } else {
                 output.push_str("dyn '_");
             }
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
+            // We've encountered a weird 'recursive type'
+            // Currently, the only way to generate such a type
+            // is by using 'impl trait':
+            //
+            // fn foo() -> impl Copy { foo }
+            //
+            // There's not really a sensible name we can generate,
+            // since we don't include 'impl trait' types (e.g. ty::Opaque)
+            // in the output
+            //
+            // Since we need to generate *something*, we just
+            // use a dummy string that should make it clear
+            // that something unusual is going on
+            if !visited.insert(t) {
+                output.push_str("<recursive_type>");
+                return;
+            }
+
+
             let sig = t.fn_sig(cx.tcx);
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
@@ -136,7 +159,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
-                    push_debuginfo_type_name(cx, parameter_type, true, output);
+                    push_debuginfo_type_name(cx, parameter_type, true, output, visited);
                     output.push_str(", ");
                 }
                 output.pop();
@@ -155,8 +178,20 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
             if !sig.output().is_unit() {
                 output.push_str(" -> ");
-                push_debuginfo_type_name(cx, sig.output(), true, output);
+                push_debuginfo_type_name(cx, sig.output(), true, output, visited);
             }
+
+
+            // We only keep the type in 'visited'
+            // for the duration of the body of this method.
+            // It's fine for a particular function type
+            // to show up multiple times in one overall type
+            // (e.g. MyType<fn() -> u8, fn() -> u8>
+            //
+            // We only care about avoiding recursing
+            // directly back to the type we're currently
+            // processing
+            visited.remove(t);
         },
         ty::Closure(..) => {
             output.push_str("closure");
@@ -200,7 +235,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     // common denominator - otherwise we would run into conflicts.
     fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                   substs: SubstsRef<'tcx>,
-                                  output: &mut String) {
+                                  output: &mut String,
+                                  visited: &mut FxHashSet<Ty<'tcx>>) {
         if substs.types().next().is_none() {
             return;
         }
@@ -208,7 +244,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         output.push('<');
 
         for type_parameter in substs.types() {
-            push_debuginfo_type_name(cx, type_parameter, true, output);
+            push_debuginfo_type_name(cx, type_parameter, true, output, visited);
             output.push_str(", ");
         }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3703ea08b62..1934f800af7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1352,7 +1352,7 @@ impl<'a> NameBinding<'a> {
         }
     }
 
-    // We sometimes need to treat variants as `pub` for backwards compatibility
+    // We sometimes need to treat variants as `pub` for backwards compatibility.
     fn pseudo_vis(&self) -> ty::Visibility {
         if self.is_variant() && self.def().def_id().is_local() {
             ty::Visibility::Public
@@ -2714,7 +2714,7 @@ impl<'a> Resolver<'a> {
     {
         let mut self_type_rib = Rib::new(NormalRibKind);
 
-        // plain insert (no renaming, types are not currently hygienic....)
+        // Plain insert (no renaming, since types are not currently hygienic)
         self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_def);
         self.ribs[TypeNS].push(self_type_rib);
         f(self);
@@ -4438,26 +4438,47 @@ impl<'a> Resolver<'a> {
             let mut collected_traits = Vec::new();
             module.for_each_child(|name, ns, binding| {
                 if ns != TypeNS { return }
-                if let Def::Trait(_) = binding.def() {
-                    collected_traits.push((name, binding));
+                match binding.def() {
+                    Def::Trait(_) |
+                    Def::TraitAlias(_) => collected_traits.push((name, binding)),
+                    _ => (),
                 }
             });
             *traits = Some(collected_traits.into_boxed_slice());
         }
 
         for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
-            let module = binding.module().unwrap();
-            let mut ident = ident;
-            if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
-                continue
-            }
-            if self.resolve_ident_in_module_unadjusted(
-                ModuleOrUniformRoot::Module(module),
-                ident,
-                ns,
-                false,
-                module.span,
-            ).is_ok() {
+            // Traits have pseudo-modules that can be used to search for the given ident.
+            if let Some(module) = binding.module() {
+                let mut ident = ident;
+                if ident.span.glob_adjust(
+                    module.expansion,
+                    binding.span.ctxt().modern(),
+                ).is_none() {
+                    continue
+                }
+                if self.resolve_ident_in_module_unadjusted(
+                    ModuleOrUniformRoot::Module(module),
+                    ident,
+                    ns,
+                    false,
+                    module.span,
+                ).is_ok() {
+                    let import_id = match binding.kind {
+                        NameBindingKind::Import { directive, .. } => {
+                            self.maybe_unused_trait_imports.insert(directive.id);
+                            self.add_to_glob_map(&directive, trait_name);
+                            Some(directive.id)
+                        }
+                        _ => None,
+                    };
+                    let trait_def_id = module.def_id().unwrap();
+                    found_traits.push(TraitCandidate { def_id: trait_def_id, import_id });
+                }
+            } else if let Def::TraitAlias(_) = binding.def() {
+                // For now, just treat all trait aliases as possible candidates, since we don't
+                // know if the ident is somewhere in the transitive bounds.
+
                 let import_id = match binding.kind {
                     NameBindingKind::Import { directive, .. } => {
                         self.maybe_unused_trait_imports.insert(directive.id);
@@ -4466,8 +4487,10 @@ impl<'a> Resolver<'a> {
                     }
                     _ => None,
                 };
-                let trait_def_id = module.def_id().unwrap();
-                found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
+                let trait_def_id = binding.def().def_id();
+                found_traits.push(TraitCandidate { def_id: trait_def_id, import_id });
+            } else {
+                bug!("candidate is not trait or trait alias?")
             }
         }
     }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 7ea07f5e0cb..97b630ba5f2 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1334,7 +1334,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         self.populate_module_if_necessary(module);
 
-        if let Some(Def::Trait(_)) = module.def() {
+        if module.is_trait() {
             self.session.span_err(directive.span, "items in traits are not importable.");
             return;
         } else if module.def_id() == directive.parent_scope.module.def_id()  {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 40dd6217335..42156213f21 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -896,20 +896,36 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         let trait_substs = self.fresh_item_substs(trait_def_id);
         let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
 
-        for item in self.impl_or_trait_item(trait_def_id) {
-            // Check whether `trait_def_id` defines a method with suitable name:
-            if !self.has_applicable_self(&item) {
-                debug!("method has inapplicable self");
-                self.record_static_candidate(TraitSource(trait_def_id));
-                continue;
-            }
+        if self.tcx.is_trait_alias(trait_def_id) {
+            // For trait aliases, assume all super-traits are relevant.
+            let bounds = iter::once(trait_ref.to_poly_trait_ref());
+            self.elaborate_bounds(bounds, |this, new_trait_ref, item| {
+                let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
+
+                let (xform_self_ty, xform_ret_ty) =
+                    this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
+                this.push_candidate(Candidate {
+                    xform_self_ty, xform_ret_ty, item, import_id,
+                    kind: TraitCandidate(new_trait_ref),
+                }, true);
+            });
+        } else {
+            debug_assert!(self.tcx.is_trait(trait_def_id));
+            for item in self.impl_or_trait_item(trait_def_id) {
+                // Check whether `trait_def_id` defines a method with suitable name.
+                if !self.has_applicable_self(&item) {
+                    debug!("method has inapplicable self");
+                    self.record_static_candidate(TraitSource(trait_def_id));
+                    continue;
+                }
 
-            let (xform_self_ty, xform_ret_ty) =
-                self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
-            self.push_candidate(Candidate {
-                xform_self_ty, xform_ret_ty, item, import_id,
-                kind: TraitCandidate(trait_ref),
-            }, false);
+                let (xform_self_ty, xform_ret_ty) =
+                    self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
+                self.push_candidate(Candidate {
+                    xform_self_ty, xform_ret_ty, item, import_id,
+                    kind: TraitCandidate(trait_ref),
+                }, false);
+            }
         }
         Ok(())
     }
@@ -930,7 +946,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             .filter(|&name| set.insert(name))
             .collect();
 
-        // sort them by the name so we have a stable result
+        // Sort them by the name so we have a stable result.
         names.sort_by_cached_key(|n| n.as_str());
         names
     }
@@ -945,6 +961,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             return r;
         }
 
+        debug!("pick: actual search failed, assemble diagnotics");
+
         let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
         let private_candidate = self.private_candidate.take();
         let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index fde0e47650d..5f5c7cfec95 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -757,9 +757,13 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
 
     impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
         fn visit_item(&mut self, i: &'v hir::Item) {
-            if let hir::ItemKind::Trait(..) = i.node {
-                let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
-                self.traits.push(def_id);
+            match i.node {
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => {
+                    let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
+                    self.traits.push(def_id);
+                }
+                _ => ()
             }
         }
 
@@ -781,7 +785,8 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
                            external_mods: &mut FxHashSet<DefId>,
                            def: Def) {
         match def {
-            Def::Trait(def_id) => {
+            Def::Trait(def_id) |
+            Def::TraitAlias(def_id) => {
                 traits.push(def_id);
             }
             Def::Mod(def_id) => {
diff --git a/src/test/codegen/fn-impl-trait-self.rs b/src/test/codegen/fn-impl-trait-self.rs
new file mode 100644
index 00000000000..f9113d50197
--- /dev/null
+++ b/src/test/codegen/fn-impl-trait-self.rs
@@ -0,0 +1,15 @@
+// compile-flags: -g
+//
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "fn() -> <recursive_type>",{{.*}}
+//
+// CHECK: {{.*}}DISubroutineType{{.*}}
+// CHECK: {{.*}}DIBasicType(name: "<recur_type>", encoding: DW_ATE_unsigned)
+
+pub fn foo() -> impl Copy {
+    foo
+}
+
+fn main() {
+    let my_res = foo();
+}
diff --git a/src/test/run-pass/issues/issue-58463.rs b/src/test/run-pass/issues/issue-58463.rs
new file mode 100644
index 00000000000..8ab845366b7
--- /dev/null
+++ b/src/test/run-pass/issues/issue-58463.rs
@@ -0,0 +1,8 @@
+// run-pass
+// compile-flags:-C debuginfo=2
+fn foo() -> impl Copy {
+    foo
+}
+fn main() {
+    foo();
+}
diff --git a/src/test/run-pass/traits/auxiliary/trait_alias.rs b/src/test/run-pass/traits/auxiliary/trait_alias.rs
new file mode 100644
index 00000000000..9e412215512
--- /dev/null
+++ b/src/test/run-pass/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,13 @@
+#![feature(trait_alias)]
+
+pub trait Hello {
+    fn hello(&self);
+}
+
+pub struct Hi;
+
+impl Hello for Hi {
+    fn hello(&self) {}
+}
+
+pub trait Greet = Hello;
diff --git a/src/test/run-pass/traits/trait-alias-import-cross-crate.rs b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs
new file mode 100644
index 00000000000..975542ab49b
--- /dev/null
+++ b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+// Import only the alias, not the real trait.
+use trait_alias::{Greet, Hi};
+
+fn main() {
+    let hi = Hi;
+    hi.hello(); // From `Hello`, via `Greet` alias.
+}
diff --git a/src/test/run-pass/traits/trait-alias-import.rs b/src/test/run-pass/traits/trait-alias-import.rs
new file mode 100644
index 00000000000..7d63320b9aa
--- /dev/null
+++ b/src/test/run-pass/traits/trait-alias-import.rs
@@ -0,0 +1,38 @@
+#![feature(trait_alias)]
+
+mod inner {
+    pub trait Foo {
+        fn foo(&self);
+    }
+
+    pub struct Qux;
+
+    impl Foo for Qux {
+        fn foo(&self) {}
+    }
+
+    pub trait Bar = Foo;
+}
+
+mod two {
+    pub trait A {
+        fn foo();
+    }
+
+    impl A for u8 {
+        fn foo() {}
+    }
+}
+
+// Import only the alias, not the `Foo` trait.
+use inner::{Bar, Qux};
+
+// Declaring an alias also brings in aliased methods.
+trait Two = two::A;
+
+fn main() {
+    let q = Qux;
+    q.foo(); // From Bar.
+
+    u8::foo(); // From A.
+}
diff --git a/src/test/ui/traits/trait-alias-ambiguous.rs b/src/test/ui/traits/trait-alias-ambiguous.rs
new file mode 100644
index 00000000000..28409e0c662
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.rs
@@ -0,0 +1,24 @@
+#![feature(trait_alias)]
+
+mod inner {
+    pub trait A { fn foo(&self); }
+    pub trait B { fn foo(&self); }
+
+    impl A for u8 {
+        fn foo(&self) {}
+    }
+    impl B for u8 {
+        fn foo(&self) {}
+    }
+
+    pub trait C = A + B;
+}
+
+use inner::C;
+
+fn main() {
+    let t = 1u8;
+    t.foo(); //~ ERROR E0034
+
+    inner::A::foo(&t); // ok
+}
diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr
new file mode 100644
index 00000000000..b7443269b88
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-ambiguous.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/trait-alias-ambiguous.rs:21:7
+   |
+LL |     t.foo();
+   |       ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:8:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8`
+  --> $DIR/trait-alias-ambiguous.rs:11:9
+   |
+LL |         fn foo(&self) {}
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.