about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-05-25 22:04:44 +0000
committerbors <bors@rust-lang.org>2020-05-25 22:04:44 +0000
commit698c5c6d95218735afebdada8a518ab66e0e9213 (patch)
tree2e31f2bab33c4c56ab1832defeae1d0184a8bf2f
parentf93bb2a50b37bc8bafe4d960e2afd839eaa854ed (diff)
parentb6a8915b2002352d2d10f5477068bebecc968761 (diff)
downloadrust-698c5c6d95218735afebdada8a518ab66e0e9213.tar.gz
rust-698c5c6d95218735afebdada8a518ab66e0e9213.zip
Auto merge of #72589 - Dylan-DPC:rollup-7l2a2bo, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #72061 (add regression tests for stalled_on const vars)
 - #72424 (fix ICE when debug-printing MIR)
 - #72450 (Fix ice-#72442)
 - #72451 (Perform MIR NRVO even if types don't match)
 - #72538 (Removed all instances of const_field.)

Failed merges:

r? @ghost
-rw-r--r--src/libcore/ops/try.rs1
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs16
-rw-r--r--src/librustc_hir/lang_items.rs2
-rw-r--r--src/librustc_middle/dep_graph/dep_node.rs1
-rw-r--r--src/librustc_middle/query/mod.rs8
-rw-r--r--src/librustc_middle/ty/print/pretty.rs30
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs2
-rw-r--r--src/librustc_mir/const_eval/mod.rs27
-rw-r--r--src/librustc_mir/lib.rs4
-rw-r--r--src/librustc_mir/transform/nrvo.rs18
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs6
-rw-r--r--src/librustc_trait_selection/traits/fulfill.rs8
-rw-r--r--src/test/ui/async-await/issue-72442.rs26
-rw-r--r--src/test/ui/async-await/issue-72442.stderr14
-rw-r--r--src/test/ui/const-generics/issue-70180-1-stalled_on.rs35
-rw-r--r--src/test/ui/const-generics/issue-70180-2-stalled_on.rs35
16 files changed, 155 insertions, 78 deletions
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs
index 996a01d413c..e15ea11569f 100644
--- a/src/libcore/ops/try.rs
+++ b/src/libcore/ops/try.rs
@@ -25,6 +25,7 @@
     )
 )]
 #[doc(alias = "?")]
+#[cfg_attr(not(bootstrap), lang = "try")]
 pub trait Try {
     /// The type of this value when viewed as successful.
     #[unstable(feature = "try_trait", issue = "42327")]
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index d2629b771c2..574f91e5b4d 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -1,6 +1,5 @@
 use crate::mir::operand::OperandRef;
 use crate::traits::*;
-use rustc_index::vec::Idx;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
 use rustc_middle::ty::layout::HasTyCtxt;
@@ -59,17 +58,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         constant
             .map(|val| {
                 let field_ty = ty.builtin_index().unwrap();
-                let fields = match ty.kind {
-                    ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()),
-                    _ => bug!("invalid simd shuffle type: {}", ty),
-                };
                 let c = ty::Const::from_value(bx.tcx(), val, ty);
-                let values: Vec<_> = (0..fields)
+                let values: Vec<_> = bx
+                    .tcx()
+                    .destructure_const(ty::ParamEnv::reveal_all().and(&c))
+                    .fields
+                    .into_iter()
                     .map(|field| {
-                        let field = bx.tcx().const_field(
-                            ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))),
-                        );
-                        if let Some(prim) = field.try_to_scalar() {
+                        if let Some(prim) = field.val.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
                             let scalar = match layout.abi {
                                 Abi::Scalar(ref x) => x,
diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs
index 04fe3b60b6a..83bada40419 100644
--- a/src/librustc_hir/lang_items.rs
+++ b/src/librustc_hir/lang_items.rs
@@ -257,4 +257,6 @@ language_item_table! {
     AlignOffsetLangItem,         "align_offset",       align_offset_fn,         Target::Fn;
 
     TerminationTraitLangItem,    "termination",        termination,             Target::Trait;
+
+    TryTraitLangItem,            "try",                try_trait,               Target::Trait;
 }
diff --git a/src/librustc_middle/dep_graph/dep_node.rs b/src/librustc_middle/dep_graph/dep_node.rs
index 33037900880..2c0524fa991 100644
--- a/src/librustc_middle/dep_graph/dep_node.rs
+++ b/src/librustc_middle/dep_graph/dep_node.rs
@@ -49,7 +49,6 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use crate::mir;
 use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
 use crate::traits::query::{
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 2445d484754..1083563c647 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -1,5 +1,4 @@
 use crate::dep_graph::SerializedDepNodeIndex;
-use crate::mir;
 use crate::mir::interpret::{GlobalId, LitToConstInput};
 use crate::traits;
 use crate::traits::query::{
@@ -553,13 +552,6 @@ rustc_queries! {
             }
         }
 
-        /// Extracts a field of a (variant of a) const.
-        query const_field(
-            key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
-        ) -> ConstValue<'tcx> {
-            desc { "extract field of const" }
-        }
-
         /// Destructure a constant ADT or array into its variant index and its
         /// field values.
         query destructure_const(
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 031ce6629bf..10426cf8561 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -1,5 +1,7 @@
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
-use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
+use crate::mir::interpret::{
+    sign_extend, truncate, AllocId, ConstValue, GlobalAlloc, Pointer, Scalar,
+};
 use crate::ty::layout::IntegerExt;
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
@@ -951,15 +953,20 @@ pub trait PrettyPrinter<'tcx>:
                     },
                     _,
                 ),
-            ) => {
-                let byte_str = self
-                    .tcx()
-                    .global_alloc(ptr.alloc_id)
-                    .unwrap_memory()
-                    .get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
-                    .unwrap();
-                p!(pretty_print_byte_str(byte_str));
-            }
+            ) => match self.tcx().get_global_alloc(ptr.alloc_id) {
+                Some(GlobalAlloc::Memory(alloc)) => {
+                    if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
+                    {
+                        p!(pretty_print_byte_str(byte_str))
+                    } else {
+                        p!(write("<too short allocation>"))
+                    }
+                }
+                // FIXME: for statics and functions, we could in principle print more detail.
+                Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
+                Some(GlobalAlloc::Function(_)) => p!(write("<function>")),
+                None => p!(write("<dangling pointer>")),
+            },
             // Bool
             (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
             (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
@@ -1018,6 +1025,9 @@ pub trait PrettyPrinter<'tcx>:
                 )?;
             }
             (Scalar::Ptr(ptr), ty::FnPtr(_)) => {
+                // FIXME: this can ICE when the ptr is dangling or points to a non-function.
+                // We should probably have a helper method to share code with the "Byte strings"
+                // printing above (which also has to handle pointers to all sorts of things).
                 let instance = self.tcx().global_alloc(ptr.alloc_id).unwrap_fn();
                 self = self.typed_value(
                     |this| this.print_value_path(instance.def_id(), instance.substs),
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index fd5e0632a2c..695e0741e35 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -122,7 +122,7 @@ pub(super) fn op_to_const<'tcx>(
     } else {
         // It is guaranteed that any non-slice scalar pair is actually ByRef here.
         // When we come back from raw const eval, we are always by-ref. The only way our op here is
-        // by-val is if we are in const_field, i.e., if this is (a field of) something that we
+        // by-val is if we are in destructure_const, i.e., if this is (a field of) something that we
         // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
         // structs containing such.
         op.try_as_mplace(ecx)
diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs
index 7f557e340bb..3539ccf5de0 100644
--- a/src/librustc_mir/const_eval/mod.rs
+++ b/src/librustc_mir/const_eval/mod.rs
@@ -5,7 +5,6 @@ use std::convert::TryFrom;
 use rustc_middle::mir;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
-use rustc_target::abi::VariantIdx;
 
 use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
 
@@ -19,32 +18,6 @@ pub use eval_queries::*;
 pub use fn_queries::*;
 pub use machine::*;
 
-/// Extracts a field of a (variant of a) const.
-// this function uses `unwrap` copiously, because an already validated constant must have valid
-// fields and can thus never fail outside of compiler bugs
-pub(crate) fn const_field<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    variant: Option<VariantIdx>,
-    field: mir::Field,
-    value: &'tcx ty::Const<'tcx>,
-) -> ConstValue<'tcx> {
-    trace!("const_field: {:?}, {:?}", field, value);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    // get the operand again
-    let op = ecx.eval_const_to_op(value, None).unwrap();
-    // downcast
-    let down = match variant {
-        None => op,
-        Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
-    };
-    // then project
-    let field = ecx.operand_field(down, field.index()).unwrap();
-    // and finally move back to the const world, always normalizing because
-    // this is not called for statics.
-    op_to_const(&ecx, field)
-}
-
 pub(crate) fn const_caller_location(
     tcx: TyCtxt<'tcx>,
     (file, line, col): (Symbol, u32, u32),
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 785c6c21d74..928d5bf88f2 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -56,10 +56,6 @@ pub fn provide(providers: &mut Providers<'_>) {
     providers.const_eval_validated = const_eval::const_eval_validated_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
     providers.const_caller_location = const_eval::const_caller_location;
-    providers.const_field = |tcx, param_env_and_value| {
-        let (param_env, (value, field)) = param_env_and_value.into_parts();
-        const_eval::const_field(tcx, param_env, None, field, value)
-    };
     providers.destructure_const = |tcx, param_env_and_value| {
         let (param_env, value) = param_env_and_value.into_parts();
         const_eval::destructure_const(tcx, param_env, value)
diff --git a/src/librustc_mir/transform/nrvo.rs b/src/librustc_mir/transform/nrvo.rs
index 941ffa94aa8..ffad1ebea00 100644
--- a/src/librustc_mir/transform/nrvo.rs
+++ b/src/librustc_mir/transform/nrvo.rs
@@ -44,18 +44,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
             }
         };
 
-        // Sometimes, the return place is assigned a local of a different but coercable type, for
-        // example `&T` instead of `&mut T`. Overwriting the `LocalInfo` for the return place would
-        // result in it having an incorrect type. Although this doesn't seem to cause a problem in
-        // codegen, bail out anyways since it happens so rarely.
-        let ret_ty = body.local_decls[mir::RETURN_PLACE].ty;
-        let assigned_ty = body.local_decls[returned_local].ty;
-        if ret_ty != assigned_ty {
-            debug!("`{:?}` was eligible for NRVO but for type mismatch", src.def_id());
-            debug!("typeof(_0) != typeof({:?}); {:?} != {:?}", returned_local, ret_ty, assigned_ty);
-            return;
-        }
-
         debug!(
             "`{:?}` was eligible for NRVO, making {:?} the return place",
             src.def_id(),
@@ -72,6 +60,12 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
         // Overwrite the debuginfo of `_0` with that of the renamed local.
         let (renamed_decl, ret_decl) =
             body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);
+
+        // Sometimes, the return place is assigned a local of a different but coercable type, for
+        // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
+        // its type may no longer match the return type of its function. This doesn't cause a
+        // problem in codegen because these two types are layout-compatible, but may be unexpected.
+        debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
         ret_decl.clone_from(renamed_decl);
 
         // The return place is always mutable.
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index b1c6815c741..50af3c12c6f 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -402,7 +402,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
                         self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
                         self.note_version_mismatch(&mut err, &trait_ref);
-                        self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
+
+                        if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
+                            self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
+                        }
+
                         if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
                             err.emit();
                             return;
diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs
index e44163f7bb1..e2ee22d8a55 100644
--- a/src/librustc_trait_selection/traits/fulfill.rs
+++ b/src/librustc_trait_selection/traits/fulfill.rs
@@ -357,7 +357,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                         // trait selection is because we don't have enough
                         // information about the types in the trait.
                         pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
+                            trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref());
 
                         debug!(
                             "process_predicate: pending obligation {:?} now stalled on {:?}",
@@ -435,7 +435,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
                     Ok(None) => {
                         let tcx = self.selcx.tcx();
                         pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
+                            trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref(tcx));
                         ProcessResult::Unchanged
                     }
                     Ok(Some(os)) => ProcessResult::Changed(mk_pending(infcx, os)),
@@ -603,8 +603,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
     }
 }
 
-/// Returns the set of type inference variables contained in a trait ref.
-fn trait_ref_type_vars<'a, 'tcx>(
+/// Returns the set of inference variables contained in a trait ref.
+fn trait_ref_infer_vars<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
 ) -> Vec<TyOrConstInferVar<'tcx>> {
diff --git a/src/test/ui/async-await/issue-72442.rs b/src/test/ui/async-await/issue-72442.rs
new file mode 100644
index 00000000000..61c8c8c1594
--- /dev/null
+++ b/src/test/ui/async-await/issue-72442.rs
@@ -0,0 +1,26 @@
+// edition:2018
+// compile-flags:-Cincremental=tmp/issue-72442
+
+use std::fs::File;
+use std::future::Future;
+use std::io::prelude::*;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    block_on(async {
+        {
+            let path = std::path::Path::new(".");
+            let mut f = File::open(path.to_str())?;
+            //~^ ERROR the trait bound
+            let mut src = String::new();
+            f.read_to_string(&mut src)?;
+            Ok(())
+        }
+    })
+}
+
+fn block_on<F>(f: F) -> F::Output
+where
+    F: Future<Output = Result<(), Box<dyn std::error::Error>>>,
+{
+    Ok(())
+}
diff --git a/src/test/ui/async-await/issue-72442.stderr b/src/test/ui/async-await/issue-72442.stderr
new file mode 100644
index 00000000000..56854333578
--- /dev/null
+++ b/src/test/ui/async-await/issue-72442.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `std::option::Option<&str>: std::convert::AsRef<std::path::Path>` is not satisfied
+  --> $DIR/issue-72442.rs:12:36
+   |
+LL |             let mut f = File::open(path.to_str())?;
+   |                                    ^^^^^^^^^^^^^ the trait `std::convert::AsRef<std::path::Path>` is not implemented for `std::option::Option<&str>`
+   | 
+  ::: $SRC_DIR/libstd/fs.rs:LL:COL
+   |
+LL |     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
+   |                    ----------- required by this bound in `std::fs::File::open`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issue-70180-1-stalled_on.rs b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs
new file mode 100644
index 00000000000..ff2a5250263
--- /dev/null
+++ b/src/test/ui/const-generics/issue-70180-1-stalled_on.rs
@@ -0,0 +1,35 @@
+// build-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+pub fn works() {
+    let array/*: [_; _]*/ = default_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+pub fn didnt_work() {
+    let array/*: [_; _]*/ = default_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+impl Foo for [i32; 4] {}
+impl Foo for [i64; 8] {}
+
+// Only needed because `[_; _]` is not valid type syntax.
+fn default_array<T, const N: usize>() -> [T; N]
+where
+    [T; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}
diff --git a/src/test/ui/const-generics/issue-70180-2-stalled_on.rs b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs
new file mode 100644
index 00000000000..83338668f4f
--- /dev/null
+++ b/src/test/ui/const-generics/issue-70180-2-stalled_on.rs
@@ -0,0 +1,35 @@
+// build-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn works() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    let _: [_; 4] = array;
+    Foo::foo(&array);
+}
+
+fn didnt_work() {
+    let array/*: [u8; _]*/ = default_byte_array();
+    Foo::foo(&array);
+    let _: [_; 4] = array;
+}
+
+trait Foo<T> {
+    fn foo(&self) {}
+}
+
+impl Foo<i32> for [u8; 4] {}
+impl Foo<i64> for [u8; 8] {}
+
+// Only needed because `[u8; _]` is not valid type syntax.
+fn default_byte_array<const N: usize>() -> [u8; N]
+where
+    [u8; N]: Default,
+{
+    Default::default()
+}
+
+fn main() {
+    works();
+    didnt_work();
+}