Rollup merge of #61987 - eddyb:hirless-resolver, r=petrochenkov

rustc: produce AST instead of HIR from `hir::lowering::Resolver` methods.

This avoids synthesizing HIR nodes in `rustc_resolve`, and `rustc::hir::lowering` patching up the result after the fact (I suspect this is even more significant for @Zoxc's chages to arena-allocate the HIR).

r? @oli-obk
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index dfc243b..400375c 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -95,30 +95,40 @@
         };
 
         build.cc.insert(target, compiler);
+        let cflags = build.cflags(target, GitRepo::Rustc);
+
+        // If we use llvm-libunwind, we will need a C++ compiler as well for all targets
+        // We'll need one anyways if the target triple is also a host triple
+        let mut cfg = cc::Build::new();
+        cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true)
+            .target(&target).host(&build.build);
+
+        let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
+            cfg.compiler(cxx);
+            true
+        } else if build.hosts.contains(&target) || build.build == target {
+            set_compiler(&mut cfg, Language::CPlusPlus, target, config, build);
+            true
+        } else {
+            false
+        };
+
+        if cxx_configured {
+            let compiler = cfg.get_compiler();
+            build.cxx.insert(target, compiler);
+        }
+
         build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target)));
-        build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc)));
+        build.verbose(&format!("CFLAGS_{} = {:?}", &target, cflags));
+        if let Ok(cxx) = build.cxx(target) {
+            build.verbose(&format!("CXX_{} = {:?}", &target, cxx));
+            build.verbose(&format!("CXXFLAGS_{} = {:?}", &target, cflags));
+        }
         if let Some(ar) = ar {
             build.verbose(&format!("AR_{} = {:?}", &target, ar));
             build.ar.insert(target, ar);
         }
     }
-
-    // For all host triples we need to find a C++ compiler as well
-    let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::<HashSet<_>>();
-    for host in hosts.into_iter() {
-        let mut cfg = cc::Build::new();
-        cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true)
-           .target(&host).host(&build.build);
-        let config = build.config.target_config.get(&host);
-        if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
-            cfg.compiler(cxx);
-        } else {
-            set_compiler(&mut cfg, Language::CPlusPlus, host, config, build);
-        }
-        let compiler = cfg.get_compiler();
-        build.verbose(&format!("CXX_{} = {:?}", host, compiler.path()));
-        build.cxx.insert(host, compiler);
-    }
 }
 
 fn set_compiler(cfg: &mut cc::Build,
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 5ce7508..0d96e5e 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -97,7 +97,7 @@
         self.ty_inhabitedness_forest(ty).contains(self, module)
     }
 
-    pub fn is_ty_uninhabited_from_all_modules(self, ty: Ty<'tcx>) -> bool {
+    pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
         !self.ty_inhabitedness_forest(ty).is_empty()
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 416b66d..f0d64e2 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -3,7 +3,6 @@
 //! After a const evaluation has computed a value, before we destroy the const evaluator's session
 //! memory, we need to extract all memory allocations to the global memory pool so they stay around.
 
-use rustc::ty::layout::LayoutOf;
 use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
 use rustc::mir::interpret::{
     InterpResult, ErrorHandled,
@@ -143,18 +142,15 @@
         // Handle Reference types, as these are the only relocations supported by const eval.
         // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
         let ty = mplace.layout.ty;
-        if let ty::Ref(_, _, mutability) = ty.sty {
+        if let ty::Ref(_, referenced_ty, mutability) = ty.sty {
             let value = self.ecx.read_immediate(mplace.into())?;
             // Handle trait object vtables
             if let Ok(meta) = value.to_meta() {
-                let layout = self.ecx.layout_of(ty.builtin_deref(true).unwrap().ty)?;
-                if layout.is_unsized() {
-                    if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(layout.ty).sty {
-                        if let Ok(vtable) = meta.unwrap().to_ptr() {
-                            // explitly choose `Immutable` here, since vtables are immutable, even
-                            // if the reference of the fat pointer is mutable
-                            self.intern_shallow(vtable, Mutability::Immutable)?;
-                        }
+                if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(referenced_ty).sty {
+                    if let Ok(vtable) = meta.unwrap().to_ptr() {
+                        // explitly choose `Immutable` here, since vtables are immutable, even
+                        // if the reference of the fat pointer is mutable
+                        self.intern_shallow(vtable, Mutability::Immutable)?;
                     }
                 }
             }
@@ -178,8 +174,14 @@
                     (InternMode::Static, hir::Mutability::MutMutable) => {},
                     // we statically prevent `&mut T` via `const_qualif` and double check this here
                     (InternMode::ConstBase, hir::Mutability::MutMutable) |
-                    (InternMode::Const, hir::Mutability::MutMutable) =>
-                        bug!("const qualif failed to prevent mutable references"),
+                    (InternMode::Const, hir::Mutability::MutMutable) => {
+                        match referenced_ty.sty {
+                            ty::Array(_, n) if n.unwrap_usize(self.ecx.tcx.tcx) == 0 => {}
+                            ty::Slice(_)
+                                if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {}
+                            _ => bug!("const qualif failed to prevent mutable references"),
+                        }
+                    },
                 }
                 // Compute the mutability with which we'll start visiting the allocation. This is
                 // what gets changed when we encounter an `UnsafeCell`
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index af061f9..a29611e 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -388,12 +388,10 @@
                             ));
                         }
                     } else {
-                        let callee_layout =
-                            self.layout_of_local(self.frame(), mir::RETURN_PLACE, None)?;
-                        if !callee_layout.abi.is_uninhabited() {
-                            return err!(FunctionRetMismatch(
-                                self.tcx.types.never, callee_layout.ty
-                            ));
+                        let local = mir::RETURN_PLACE;
+                        let ty = self.frame().body.local_decls[local].ty;
+                        if !self.tcx.is_ty_uninhabited_from_any_module(ty) {
+                            return err!(FunctionRetMismatch(self.tcx.types.never, ty));
                         }
                     }
                     Ok(())
diff --git a/src/test/ui/consts/issue-62045.rs b/src/test/ui/consts/issue-62045.rs
new file mode 100644
index 0000000..9f41ed9
--- /dev/null
+++ b/src/test/ui/consts/issue-62045.rs
@@ -0,0 +1,5 @@
+// compile-pass
+
+fn main() {
+    assert_eq!(&mut [0; 1][..], &mut []);
+}
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs
index 4a77534..4fcd89a 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs
@@ -3,6 +3,7 @@
 // rustc-env:RUST_BACKTRACE=0
 // normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
 // normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
+// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC"
 
 #![allow(const_err)]
 
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
index ff2351e..82569e2 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr
@@ -1,12 +1,12 @@
 warning: skipping const checks
-  --> $DIR/mutable_references_ice.rs:26:9
+  --> $DIR/mutable_references_ice.rs:27:9
    |
 LL |         *MUH.x.get() = 99;
    |         ^^^^^^^^^^^^^^^^^
 
 thread 'rustc' panicked at 'assertion failed: `(left != right)`
   left: `Const`,
- right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:127:17
+ right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.rs b/src/test/ui/consts/uninhabited-const-issue-61744.rs
new file mode 100644
index 0000000..21fbbf8
--- /dev/null
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.rs
@@ -0,0 +1,19 @@
+// compile-fail
+
+pub const unsafe fn fake_type<T>() -> T {
+    hint_unreachable()
+}
+
+pub const unsafe fn hint_unreachable() -> ! {
+    fake_type() //~ ERROR any use of this value will cause an error
+}
+
+trait Const {
+    const CONSTANT: i32 = unsafe { fake_type() };
+}
+
+impl <T> Const for T {}
+
+pub fn main() -> () {
+    dbg!(i32::CONSTANT); //~ ERROR erroneous constant used
+}
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
new file mode 100644
index 0000000..5c28554
--- /dev/null
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -0,0 +1,24 @@
+error: any use of this value will cause an error
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+   |     |
+   |     tried to call a function with return type T passing return place of type !
+   |     inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
+   |     inside call to `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:12:36
+...
+LL |     const CONSTANT: i32 = unsafe { fake_type() };
+   |     ---------------------------------------------
+   |
+   = note: #[deny(const_err)] on by default
+
+error[E0080]: erroneous constant used
+  --> $DIR/uninhabited-const-issue-61744.rs:18:10
+   |
+LL |     dbg!(i32::CONSTANT);
+   |          ^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.