Skip to content

Commit 698c5c6

Browse files
committed
Auto merge of rust-lang#72589 - Dylan-DPC:rollup-7l2a2bo, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - rust-lang#72061 (add regression tests for stalled_on const vars) - rust-lang#72424 (fix ICE when debug-printing MIR) - rust-lang#72450 (Fix ice-rust-lang#72442) - rust-lang#72451 (Perform MIR NRVO even if types don't match) - rust-lang#72538 (Removed all instances of const_field.) Failed merges: r? @ghost
2 parents f93bb2a + b6a8915 commit 698c5c6

File tree

16 files changed

+155
-78
lines changed

16 files changed

+155
-78
lines changed

src/libcore/ops/try.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
)
2626
)]
2727
#[doc(alias = "?")]
28+
#[cfg_attr(not(bootstrap), lang = "try")]
2829
pub trait Try {
2930
/// The type of this value when viewed as successful.
3031
#[unstable(feature = "try_trait", issue = "42327")]

src/librustc_codegen_ssa/mir/constant.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::mir::operand::OperandRef;
22
use crate::traits::*;
3-
use rustc_index::vec::Idx;
43
use rustc_middle::mir;
54
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
65
use rustc_middle::ty::layout::HasTyCtxt;
@@ -59,17 +58,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
5958
constant
6059
.map(|val| {
6160
let field_ty = ty.builtin_index().unwrap();
62-
let fields = match ty.kind {
63-
ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()),
64-
_ => bug!("invalid simd shuffle type: {}", ty),
65-
};
6661
let c = ty::Const::from_value(bx.tcx(), val, ty);
67-
let values: Vec<_> = (0..fields)
62+
let values: Vec<_> = bx
63+
.tcx()
64+
.destructure_const(ty::ParamEnv::reveal_all().and(&c))
65+
.fields
66+
.into_iter()
6867
.map(|field| {
69-
let field = bx.tcx().const_field(
70-
ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))),
71-
);
72-
if let Some(prim) = field.try_to_scalar() {
68+
if let Some(prim) = field.val.try_to_scalar() {
7369
let layout = bx.layout_of(field_ty);
7470
let scalar = match layout.abi {
7571
Abi::Scalar(ref x) => x,

src/librustc_hir/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,6 @@ language_item_table! {
257257
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
258258

259259
TerminationTraitLangItem, "termination", termination, Target::Trait;
260+
261+
TryTraitLangItem, "try", try_trait, Target::Trait;
260262
}

src/librustc_middle/dep_graph/dep_node.rs

-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
//! user of the `DepNode` API of having to know how to compute the expected
5050
//! fingerprint for a given set of node parameters.
5151
52-
use crate::mir;
5352
use crate::mir::interpret::{GlobalId, LitToConstInput};
5453
use crate::traits;
5554
use crate::traits::query::{

src/librustc_middle/query/mod.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::dep_graph::SerializedDepNodeIndex;
2-
use crate::mir;
32
use crate::mir::interpret::{GlobalId, LitToConstInput};
43
use crate::traits;
54
use crate::traits::query::{
@@ -553,13 +552,6 @@ rustc_queries! {
553552
}
554553
}
555554

556-
/// Extracts a field of a (variant of a) const.
557-
query const_field(
558-
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
559-
) -> ConstValue<'tcx> {
560-
desc { "extract field of const" }
561-
}
562-
563555
/// Destructure a constant ADT or array into its variant index and its
564556
/// field values.
565557
query destructure_const(

src/librustc_middle/ty/print/pretty.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
2-
use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
2+
use crate::mir::interpret::{
3+
sign_extend, truncate, AllocId, ConstValue, GlobalAlloc, Pointer, Scalar,
4+
};
35
use crate::ty::layout::IntegerExt;
46
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
57
use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
@@ -951,15 +953,20 @@ pub trait PrettyPrinter<'tcx>:
951953
},
952954
_,
953955
),
954-
) => {
955-
let byte_str = self
956-
.tcx()
957-
.global_alloc(ptr.alloc_id)
958-
.unwrap_memory()
959-
.get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
960-
.unwrap();
961-
p!(pretty_print_byte_str(byte_str));
962-
}
956+
) => match self.tcx().get_global_alloc(ptr.alloc_id) {
957+
Some(GlobalAlloc::Memory(alloc)) => {
958+
if let Ok(byte_str) = alloc.get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
959+
{
960+
p!(pretty_print_byte_str(byte_str))
961+
} else {
962+
p!(write("<too short allocation>"))
963+
}
964+
}
965+
// FIXME: for statics and functions, we could in principle print more detail.
966+
Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
967+
Some(GlobalAlloc::Function(_)) => p!(write("<function>")),
968+
None => p!(write("<dangling pointer>")),
969+
},
963970
// Bool
964971
(Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
965972
(Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
@@ -1018,6 +1025,9 @@ pub trait PrettyPrinter<'tcx>:
10181025
)?;
10191026
}
10201027
(Scalar::Ptr(ptr), ty::FnPtr(_)) => {
1028+
// FIXME: this can ICE when the ptr is dangling or points to a non-function.
1029+
// We should probably have a helper method to share code with the "Byte strings"
1030+
// printing above (which also has to handle pointers to all sorts of things).
10211031
let instance = self.tcx().global_alloc(ptr.alloc_id).unwrap_fn();
10221032
self = self.typed_value(
10231033
|this| this.print_value_path(instance.def_id(), instance.substs),

src/librustc_mir/const_eval/eval_queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub(super) fn op_to_const<'tcx>(
122122
} else {
123123
// It is guaranteed that any non-slice scalar pair is actually ByRef here.
124124
// When we come back from raw const eval, we are always by-ref. The only way our op here is
125-
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
125+
// by-val is if we are in destructure_const, i.e., if this is (a field of) something that we
126126
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
127127
// structs containing such.
128128
op.try_as_mplace(ecx)

src/librustc_mir/const_eval/mod.rs

-27
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::convert::TryFrom;
55
use rustc_middle::mir;
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
8-
use rustc_target::abi::VariantIdx;
98

109
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
1110

@@ -19,32 +18,6 @@ pub use eval_queries::*;
1918
pub use fn_queries::*;
2019
pub use machine::*;
2120

22-
/// Extracts a field of a (variant of a) const.
23-
// this function uses `unwrap` copiously, because an already validated constant must have valid
24-
// fields and can thus never fail outside of compiler bugs
25-
pub(crate) fn const_field<'tcx>(
26-
tcx: TyCtxt<'tcx>,
27-
param_env: ty::ParamEnv<'tcx>,
28-
variant: Option<VariantIdx>,
29-
field: mir::Field,
30-
value: &'tcx ty::Const<'tcx>,
31-
) -> ConstValue<'tcx> {
32-
trace!("const_field: {:?}, {:?}", field, value);
33-
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
34-
// get the operand again
35-
let op = ecx.eval_const_to_op(value, None).unwrap();
36-
// downcast
37-
let down = match variant {
38-
None => op,
39-
Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
40-
};
41-
// then project
42-
let field = ecx.operand_field(down, field.index()).unwrap();
43-
// and finally move back to the const world, always normalizing because
44-
// this is not called for statics.
45-
op_to_const(&ecx, field)
46-
}
47-
4821
pub(crate) fn const_caller_location(
4922
tcx: TyCtxt<'tcx>,
5023
(file, line, col): (Symbol, u32, u32),

src/librustc_mir/lib.rs

-4
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ pub fn provide(providers: &mut Providers<'_>) {
5656
providers.const_eval_validated = const_eval::const_eval_validated_provider;
5757
providers.const_eval_raw = const_eval::const_eval_raw_provider;
5858
providers.const_caller_location = const_eval::const_caller_location;
59-
providers.const_field = |tcx, param_env_and_value| {
60-
let (param_env, (value, field)) = param_env_and_value.into_parts();
61-
const_eval::const_field(tcx, param_env, None, field, value)
62-
};
6359
providers.destructure_const = |tcx, param_env_and_value| {
6460
let (param_env, value) = param_env_and_value.into_parts();
6561
const_eval::destructure_const(tcx, param_env, value)

src/librustc_mir/transform/nrvo.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
4444
}
4545
};
4646

47-
// Sometimes, the return place is assigned a local of a different but coercable type, for
48-
// example `&T` instead of `&mut T`. Overwriting the `LocalInfo` for the return place would
49-
// result in it having an incorrect type. Although this doesn't seem to cause a problem in
50-
// codegen, bail out anyways since it happens so rarely.
51-
let ret_ty = body.local_decls[mir::RETURN_PLACE].ty;
52-
let assigned_ty = body.local_decls[returned_local].ty;
53-
if ret_ty != assigned_ty {
54-
debug!("`{:?}` was eligible for NRVO but for type mismatch", src.def_id());
55-
debug!("typeof(_0) != typeof({:?}); {:?} != {:?}", returned_local, ret_ty, assigned_ty);
56-
return;
57-
}
58-
5947
debug!(
6048
"`{:?}` was eligible for NRVO, making {:?} the return place",
6149
src.def_id(),
@@ -72,6 +60,12 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
7260
// Overwrite the debuginfo of `_0` with that of the renamed local.
7361
let (renamed_decl, ret_decl) =
7462
body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);
63+
64+
// Sometimes, the return place is assigned a local of a different but coercable type, for
65+
// example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
66+
// its type may no longer match the return type of its function. This doesn't cause a
67+
// problem in codegen because these two types are layout-compatible, but may be unexpected.
68+
debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
7569
ret_decl.clone_from(renamed_decl);
7670

7771
// The return place is always mutable.

src/librustc_trait_selection/traits/error_reporting/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
402402
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
403403
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
404404
self.note_version_mismatch(&mut err, &trait_ref);
405-
self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
405+
406+
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
407+
self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
408+
}
409+
406410
if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
407411
err.emit();
408412
return;

src/librustc_trait_selection/traits/fulfill.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
357357
// trait selection is because we don't have enough
358358
// information about the types in the trait.
359359
pending_obligation.stalled_on =
360-
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
360+
trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref());
361361

362362
debug!(
363363
"process_predicate: pending obligation {:?} now stalled on {:?}",
@@ -435,7 +435,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
435435
Ok(None) => {
436436
let tcx = self.selcx.tcx();
437437
pending_obligation.stalled_on =
438-
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
438+
trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref(tcx));
439439
ProcessResult::Unchanged
440440
}
441441
Ok(Some(os)) => ProcessResult::Changed(mk_pending(infcx, os)),
@@ -603,8 +603,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
603603
}
604604
}
605605

606-
/// Returns the set of type inference variables contained in a trait ref.
607-
fn trait_ref_type_vars<'a, 'tcx>(
606+
/// Returns the set of inference variables contained in a trait ref.
607+
fn trait_ref_infer_vars<'a, 'tcx>(
608608
selcx: &mut SelectionContext<'a, 'tcx>,
609609
trait_ref: ty::PolyTraitRef<'tcx>,
610610
) -> Vec<TyOrConstInferVar<'tcx>> {
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// edition:2018
2+
// compile-flags:-Cincremental=tmp/issue-72442
3+
4+
use std::fs::File;
5+
use std::future::Future;
6+
use std::io::prelude::*;
7+
8+
fn main() -> Result<(), Box<dyn std::error::Error>> {
9+
block_on(async {
10+
{
11+
let path = std::path::Path::new(".");
12+
let mut f = File::open(path.to_str())?;
13+
//~^ ERROR the trait bound
14+
let mut src = String::new();
15+
f.read_to_string(&mut src)?;
16+
Ok(())
17+
}
18+
})
19+
}
20+
21+
fn block_on<F>(f: F) -> F::Output
22+
where
23+
F: Future<Output = Result<(), Box<dyn std::error::Error>>>,
24+
{
25+
Ok(())
26+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0277]: the trait bound `std::option::Option<&str>: std::convert::AsRef<std::path::Path>` is not satisfied
2+
--> $DIR/issue-72442.rs:12:36
3+
|
4+
LL | let mut f = File::open(path.to_str())?;
5+
| ^^^^^^^^^^^^^ the trait `std::convert::AsRef<std::path::Path>` is not implemented for `std::option::Option<&str>`
6+
|
7+
::: $SRC_DIR/libstd/fs.rs:LL:COL
8+
|
9+
LL | pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
10+
| ----------- required by this bound in `std::fs::File::open`
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// build-pass
2+
#![feature(const_generics)]
3+
#![allow(incomplete_features)]
4+
5+
pub fn works() {
6+
let array/*: [_; _]*/ = default_array();
7+
let _: [_; 4] = array;
8+
Foo::foo(&array);
9+
}
10+
11+
pub fn didnt_work() {
12+
let array/*: [_; _]*/ = default_array();
13+
Foo::foo(&array);
14+
let _: [_; 4] = array;
15+
}
16+
17+
trait Foo {
18+
fn foo(&self) {}
19+
}
20+
21+
impl Foo for [i32; 4] {}
22+
impl Foo for [i64; 8] {}
23+
24+
// Only needed because `[_; _]` is not valid type syntax.
25+
fn default_array<T, const N: usize>() -> [T; N]
26+
where
27+
[T; N]: Default,
28+
{
29+
Default::default()
30+
}
31+
32+
fn main() {
33+
works();
34+
didnt_work();
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// build-pass
2+
#![feature(const_generics)]
3+
#![allow(incomplete_features)]
4+
5+
fn works() {
6+
let array/*: [u8; _]*/ = default_byte_array();
7+
let _: [_; 4] = array;
8+
Foo::foo(&array);
9+
}
10+
11+
fn didnt_work() {
12+
let array/*: [u8; _]*/ = default_byte_array();
13+
Foo::foo(&array);
14+
let _: [_; 4] = array;
15+
}
16+
17+
trait Foo<T> {
18+
fn foo(&self) {}
19+
}
20+
21+
impl Foo<i32> for [u8; 4] {}
22+
impl Foo<i64> for [u8; 8] {}
23+
24+
// Only needed because `[u8; _]` is not valid type syntax.
25+
fn default_byte_array<const N: usize>() -> [u8; N]
26+
where
27+
[u8; N]: Default,
28+
{
29+
Default::default()
30+
}
31+
32+
fn main() {
33+
works();
34+
didnt_work();
35+
}

0 commit comments

Comments
 (0)