From 6550c970b5983b6d96aff1959793430dff49d1fc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Dec 2018 13:32:09 -0800 Subject: [PATCH 01/28] ci: Upgrade Travis to Xenial In theory we shouldn't require trusty so long as docker continues to work! --- .travis.yml | 2 +- src/ci/docker/run.sh | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f99678499ace..c4efa88460325 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: shell sudo: required -dist: trusty +dist: xenial services: - docker addons: diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index ebef27360c02b..ad6188568cff2 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -19,10 +19,12 @@ travis_time_start if [ -f "$docker_dir/$image/Dockerfile" ]; then if [ "$CI" != "" ]; then - cksum=$(find $docker_dir/$image $docker_dir/scripts -type f | \ + hash_key=/tmp/.docker-hash-key.txt + find $docker_dir/$image $docker_dir/scripts -type f | \ sort | \ - xargs cat | \ - sha512sum | \ + xargs cat >> $hash_key + docker --version >> $hash_key + cksum=$(sha512sum $hash_key | \ awk '{print $1}') s3url="s3://$SCCACHE_BUCKET/docker/$cksum" url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" From 28907aaf602f50db1b302d20d72e54aabf0b479b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 3 Jan 2019 12:59:54 -0800 Subject: [PATCH 02/28] Update cargo --- Cargo.lock | 2 ++ src/tools/cargo | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 041a24aae6c53..6f24f8d3681d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -194,6 +194,7 @@ version = "0.34.0" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -241,6 +242,7 @@ dependencies = [ "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/tools/cargo b/src/tools/cargo index 0d1f1bbeabd5b..34320d212dca8 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0d1f1bbeabd5b43a7f3ecfa16540af8e76d5efb4 +Subproject commit 34320d212dca8cd27d06ce93c16c6151f46fcf2e From 80f914d47b9f5e23533ec6e01794f4c404094f35 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Nov 2018 11:27:09 +0100 Subject: [PATCH 03/28] test: Add test for issues 45510 and 18952. Those tests are directly taken from the comments on the bug reports. --- src/test/run-pass/issue-18952.rs | 48 ++++++++++++++++++++++++++++++++ src/test/run-pass/issue-45510.rs | 27 ++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/test/run-pass/issue-18952.rs create mode 100644 src/test/run-pass/issue-45510.rs diff --git a/src/test/run-pass/issue-18952.rs b/src/test/run-pass/issue-18952.rs new file mode 100644 index 0000000000000..ca2645ca9e5d9 --- /dev/null +++ b/src/test/run-pass/issue-18952.rs @@ -0,0 +1,48 @@ +// This issue tests fn_traits overloading on arity. + +#![feature(fn_traits)] +#![feature(unboxed_closures)] + +struct Foo; + +impl Fn<(isize, isize)> for Foo { + extern "rust-call" fn call(&self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} + +impl FnMut<(isize, isize)> for Foo { + extern "rust-call" fn call_mut(&mut self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} + +impl FnOnce<(isize, isize)> for Foo { + type Output = (); + extern "rust-call" fn call_once(self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} + +impl Fn<(isize, isize, isize)> for Foo { + extern "rust-call" fn call(&self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} + +impl FnMut<(isize, isize, isize)> for Foo { + extern "rust-call" fn call_mut(&mut self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} +impl FnOnce<(isize, isize, isize)> for Foo { + type Output = (); + extern "rust-call" fn call_once(self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + } +} + +fn main() { + let foo = Foo; + foo(1, 1); +} diff --git a/src/test/run-pass/issue-45510.rs b/src/test/run-pass/issue-45510.rs new file mode 100644 index 0000000000000..922a26b903094 --- /dev/null +++ b/src/test/run-pass/issue-45510.rs @@ -0,0 +1,27 @@ +// Test overloaded resolution of fn_traits. + +#![feature(fn_traits)] +#![feature(unboxed_closures)] + +struct Ishmael; +struct Maybe; +struct CallMe; + +impl FnOnce<(Ishmael,)> for CallMe { + type Output = (); + extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> () { + println!("Split your lungs with blood and thunder!"); + } +} + +impl FnOnce<(Maybe,)> for CallMe { + type Output = (); + extern "rust-call" fn call_once(self, _args: (Maybe,)) -> () { + println!("So we just met, and this is crazy"); + } +} + +fn main() { + CallMe(Ishmael); + CallMe(Maybe); +} From 839876ccd1c16efefc523792d7ae71f411994884 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Nov 2018 16:14:44 +0100 Subject: [PATCH 04/28] rustfmt: librust_typeck/check/callee.rs --- src/librustc_typeck/check/callee.rs | 344 ++++++++++++++++------------ 1 file changed, 200 insertions(+), 144 deletions(-) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index d4f639c070de3..727fbf7b30f67 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -1,16 +1,16 @@ -use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use super::autoderef::Autoderef; use super::method::MethodCallee; +use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; +use errors::Applicability; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, TypeFoldable, Ty}; -use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_target::spec::abi; use syntax::ast::Ident; use syntax_pos::Span; -use errors::Applicability; use rustc::hir; @@ -33,12 +33,13 @@ enum CallStep<'tcx> { } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn check_call(&self, - call_expr: &'gcx hir::Expr, - callee_expr: &'gcx hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>) - -> Ty<'tcx> { + pub fn check_call( + &self, + call_expr: &'gcx hir::Expr, + callee_expr: &'gcx hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + ) -> Ty<'tcx> { let original_callee_ty = self.check_expr(callee_expr); let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); @@ -74,15 +75,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { output } - fn try_overloaded_call_step(&self, - call_expr: &'gcx hir::Expr, - callee_expr: &'gcx hir::Expr, - autoderef: &Autoderef<'a, 'gcx, 'tcx>) - -> Option> { + fn try_overloaded_call_step( + &self, + call_expr: &'gcx hir::Expr, + callee_expr: &'gcx hir::Expr, + autoderef: &Autoderef<'a, 'gcx, 'tcx>, + ) -> Option> { let adjusted_ty = autoderef.unambiguous_final_ty(self); - debug!("try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", - call_expr, - adjusted_ty); + debug!( + "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", + call_expr, adjusted_ty + ); // If the callee is a bare function or a closure, then we're all set. match adjusted_ty.sty { @@ -100,21 +103,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id, substs).is_none() { let closure_ty = self.closure_sig(def_id, substs); - let fn_sig = self.replace_bound_vars_with_fresh_vars( - call_expr.span, - infer::FnCall, - &closure_ty - ).0; + let fn_sig = self + .replace_bound_vars_with_fresh_vars( + call_expr.span, + infer::FnCall, + &closure_ty, + ) + .0; let adjustments = autoderef.adjust_steps(self, Needs::None); - self.record_deferred_call_resolution(def_id, DeferredCallResolution { - call_expr, - callee_expr, - adjusted_ty, - adjustments, - fn_sig, - closure_def_id: def_id, - closure_substs: substs, - }); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + adjusted_ty, + adjustments, + fn_sig, + closure_def_id: def_id, + closure_substs: substs, + }, + ); return Some(CallStep::DeferredClosure(fn_sig)); } } @@ -134,34 +142,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } - self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| { - let mut adjustments = autoderef.adjust_steps(self, Needs::None); - adjustments.extend(autoref); - self.apply_adjustments(callee_expr, adjustments); - CallStep::Overloaded(method) - }) + self.try_overloaded_call_traits(call_expr, adjusted_ty) + .map(|(autoref, method)| { + let mut adjustments = autoderef.adjust_steps(self, Needs::None); + adjustments.extend(autoref); + self.apply_adjustments(callee_expr, adjustments); + CallStep::Overloaded(method) + }) } - fn try_overloaded_call_traits(&self, - call_expr: &hir::Expr, - adjusted_ty: Ty<'tcx>) - -> Option<(Option>, - MethodCallee<'tcx>)> { + fn try_overloaded_call_traits( + &self, + call_expr: &hir::Expr, + adjusted_ty: Ty<'tcx>, + ) -> Option<(Option>, MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. - for &(opt_trait_def_id, method_name, borrow) in - &[(self.tcx.lang_items().fn_trait(), Ident::from_str("call"), true), - (self.tcx.lang_items().fn_mut_trait(), Ident::from_str("call_mut"), true), - (self.tcx.lang_items().fn_once_trait(), Ident::from_str("call_once"), false)] { + for &(opt_trait_def_id, method_name, borrow) in &[ + ( + self.tcx.lang_items().fn_trait(), + Ident::from_str("call"), + true, + ), + ( + self.tcx.lang_items().fn_mut_trait(), + Ident::from_str("call_mut"), + true, + ), + ( + self.tcx.lang_items().fn_once_trait(), + Ident::from_str("call_once"), + false, + ), + ] { let trait_def_id = match opt_trait_def_id { Some(def_id) => def_id, None => continue, }; - if let Some(ok) = self.lookup_method_in_trait(call_expr.span, - method_name, - trait_def_id, - adjusted_ty, - None) { + if let Some(ok) = self.lookup_method_in_trait( + call_expr.span, + method_name, + trait_def_id, + adjusted_ty, + None, + ) { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { @@ -173,11 +197,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // deployment, conservatively omit // overloaded function call ops. allow_two_phase_borrow: AllowTwoPhase::No, - } + }, }; autoref = Some(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)), - target: method.sig.inputs()[0] + target: method.sig.inputs()[0], }); } } @@ -188,16 +212,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - fn confirm_builtin_call(&self, - call_expr: &hir::Expr, - callee_ty: Ty<'tcx>, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>) - -> Ty<'tcx> { + fn confirm_builtin_call( + &self, + call_expr: &hir::Expr, + callee_ty: Ty<'tcx>, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + ) -> Ty<'tcx> { let (fn_sig, def_span) = match callee_ty.sty { - ty::FnDef(def_id, _) => { - (callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id)) - } + ty::FnDef(def_id, _) => ( + callee_ty.fn_sig(self.tcx), + self.tcx.hir().span_if_local(def_id), + ), ty::FnPtr(sig) => (sig, None), ref t => { let mut unit_variant = None; @@ -219,15 +245,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match unit_variant { Some(ref path) => format!("enum variant `{}`", path), None => format!("`{}`", callee_ty), - }); + } + ); if let Some(ref path) = unit_variant { err.span_suggestion_with_applicability( call_expr.span, - &format!("`{}` is a unit variant, you need to write it \ - without the parenthesis", path), + &format!( + "`{}` is a unit variant, you need to write it \ + without the parenthesis", + path + ), path.to_string(), - Applicability::MachineApplicable + Applicability::MachineApplicable, ); } @@ -235,48 +265,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let def = match callee.node { hir::ExprKind::Path(ref qpath) => { self.tables.borrow().qpath_def(qpath, callee.hir_id) - }, + } hir::ExprKind::Call(ref inner_callee, _) => { // If the call spans more than one line and the callee kind is // itself another `ExprCall`, that's a clue that we might just be // missing a semicolon (Issue #51055) - let call_is_multiline = self.tcx.sess.source_map() - .is_multiline(call_expr.span); + let call_is_multiline = + self.tcx.sess.source_map().is_multiline(call_expr.span); if call_is_multiline { let span = self.tcx.sess.source_map().next_point(callee.span); err.span_suggestion_with_applicability( span, "try adding a semicolon", ";".to_owned(), - Applicability::MaybeIncorrect + Applicability::MaybeIncorrect, ); } if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.node { inner_callee_path = Some(inner_qpath); - self.tables.borrow().qpath_def(inner_qpath, inner_callee.hir_id) + self.tables + .borrow() + .qpath_def(inner_qpath, inner_callee.hir_id) } else { Def::Err } - }, - _ => { - Def::Err } + _ => Def::Err, }; err.span_label(call_expr.span, "call expression requires function"); let def_span = match def { Def::Err => None, - Def::Local(id) | Def::Upvar(id, ..) => { - Some(self.tcx.hir().span(id)) - } - _ => def.opt_def_id().and_then(|did| self.tcx.hir().span_if_local(did)), + Def::Local(id) | Def::Upvar(id, ..) => Some(self.tcx.hir().span(id)), + _ => def + .opt_def_id() + .and_then(|did| self.tcx.hir().span_if_local(did)), }; if let Some(span) = def_span { let label = match (unit_variant, inner_callee_path) { (Some(path), _) => format!("`{}` defined here", path), (_, Some(hir::QPath::Resolved(_, path))) => format!( - "`{}` defined here returns `{}`", path, callee_ty.to_string() + "`{}` defined here returns `{}`", + path, + callee_ty.to_string() ), _ => format!("`{}` defined here", callee_ty.to_string()), }; @@ -284,19 +316,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } err.emit(); } else { - bug!("call_expr.node should be an ExprKind::Call, got {:?}", call_expr.node); + bug!( + "call_expr.node should be an ExprKind::Call, got {:?}", + call_expr.node + ); } // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. - (ty::Binder::bind(self.tcx.mk_fn_sig( - self.err_args(arg_exprs.len()).into_iter(), - self.tcx.types.err, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - )), None) + ( + ty::Binder::bind(self.tcx.mk_fn_sig( + self.err_args(arg_exprs.len()).into_iter(), + self.tcx.types.err, + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + )), + None, + ) } }; @@ -305,69 +343,80 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // renormalize the associated types at this point, since they // previously appeared within a `Binder<>` and hence would not // have been normalized before. - let fn_sig = - self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig) - .0; + let fn_sig = self + .replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig) + .0; let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); // Call the generic checker. - let expected_arg_tys = - self.expected_inputs_for_expected_output(call_expr.span, - expected, - fn_sig.output(), - fn_sig.inputs()); - self.check_argument_types(call_expr.span, - call_expr.span, - fn_sig.inputs(), - &expected_arg_tys[..], - arg_exprs, - fn_sig.variadic, - TupleArgumentsFlag::DontTupleArguments, - def_span); + let expected_arg_tys = self.expected_inputs_for_expected_output( + call_expr.span, + expected, + fn_sig.output(), + fn_sig.inputs(), + ); + self.check_argument_types( + call_expr.span, + call_expr.span, + fn_sig.inputs(), + &expected_arg_tys[..], + arg_exprs, + fn_sig.variadic, + TupleArgumentsFlag::DontTupleArguments, + def_span, + ); fn_sig.output() } - fn confirm_deferred_closure_call(&self, - call_expr: &hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>, - fn_sig: ty::FnSig<'tcx>) - -> Ty<'tcx> { + fn confirm_deferred_closure_call( + &self, + call_expr: &hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + fn_sig: ty::FnSig<'tcx>, + ) -> Ty<'tcx> { // `fn_sig` is the *signature* of the cosure being called. We // don't know the full details yet (`Fn` vs `FnMut` etc), but we // do know the types expected for each argument and the return // type. - let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span, - expected, - fn_sig.output().clone(), - fn_sig.inputs()); - - self.check_argument_types(call_expr.span, - call_expr.span, - fn_sig.inputs(), - &expected_arg_tys, - arg_exprs, - fn_sig.variadic, - TupleArgumentsFlag::TupleArguments, - None); + let expected_arg_tys = self.expected_inputs_for_expected_output( + call_expr.span, + expected, + fn_sig.output().clone(), + fn_sig.inputs(), + ); + + self.check_argument_types( + call_expr.span, + call_expr.span, + fn_sig.inputs(), + &expected_arg_tys, + arg_exprs, + fn_sig.variadic, + TupleArgumentsFlag::TupleArguments, + None, + ); fn_sig.output() } - fn confirm_overloaded_call(&self, - call_expr: &hir::Expr, - arg_exprs: &'gcx [hir::Expr], - expected: Expectation<'tcx>, - method_callee: MethodCallee<'tcx>) - -> Ty<'tcx> { - let output_type = self.check_method_argument_types(call_expr.span, - call_expr.span, - Ok(method_callee), - arg_exprs, - TupleArgumentsFlag::TupleArguments, - expected); + fn confirm_overloaded_call( + &self, + call_expr: &hir::Expr, + arg_exprs: &'gcx [hir::Expr], + expected: Expectation<'tcx>, + method_callee: MethodCallee<'tcx>, + ) -> Ty<'tcx> { + let output_type = self.check_method_argument_types( + call_expr.span, + call_expr.span, + Ok(method_callee), + arg_exprs, + TupleArgumentsFlag::TupleArguments, + expected, + ); self.write_method_call(call_expr.hir_id, method_callee); output_type @@ -391,11 +440,12 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some()); + assert!(fcx + .closure_kind(self.closure_def_id, self.closure_substs) + .is_some()); // We may now know enough to figure out fn vs fnmut etc. - match fcx.try_overloaded_call_traits(self.call_expr, - self.adjusted_ty) { + match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature @@ -410,22 +460,28 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { debug!("attempt_resolution: method_callee={:?}", method_callee); for (method_arg_ty, self_arg_ty) in - method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) { + method_sig.inputs().iter().skip(1).zip(self.fn_sig.inputs()) + { fcx.demand_eqtype(self.call_expr.span, &self_arg_ty, &method_arg_ty); } - fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output()); + fcx.demand_eqtype( + self.call_expr.span, + method_sig.output(), + self.fn_sig.output(), + ); let mut adjustments = self.adjustments; adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.hir_id, - method_callee); + fcx.write_method_call(self.call_expr.hir_id, method_callee); } None => { - span_bug!(self.call_expr.span, - "failed to find an overloaded call trait for closure call"); + span_bug!( + self.call_expr.span, + "failed to find an overloaded call trait for closure call" + ); } } } From cf40a3e1195143301edd475e0ab8e4eaab8d54b8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Nov 2018 11:23:45 +0100 Subject: [PATCH 05/28] rustc_typeck: Implement resolution advised in issue 45510. When resolving Fn traits, the compiler failed to take into account overloaded implementations. To resolve this, we inform the trait dispatch code that the arguments will becoming as a tuple of correct arity. --- src/librustc_typeck/check/callee.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 727fbf7b30f67..5a79bec4dd72d 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -8,6 +8,7 @@ use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::{infer, traits}; +use rustc::infer::type_variable::TypeVariableOrigin; use rustc_target::spec::abi; use syntax::ast::Ident; use syntax_pos::Span; @@ -46,7 +47,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut autoderef = self.autoderef(callee_expr.span, expr_ty); let mut result = None; while result.is_none() && autoderef.next().is_some() { - result = self.try_overloaded_call_step(call_expr, callee_expr, &autoderef); + result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); } autoderef.finalize(self); @@ -79,6 +80,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, call_expr: &'gcx hir::Expr, callee_expr: &'gcx hir::Expr, + arg_exprs: &'gcx [hir::Expr], autoderef: &Autoderef<'a, 'gcx, 'tcx>, ) -> Option> { let adjusted_ty = autoderef.unambiguous_final_ty(self); @@ -142,7 +144,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } - self.try_overloaded_call_traits(call_expr, adjusted_ty) + self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) .map(|(autoref, method)| { let mut adjustments = autoderef.adjust_steps(self, Needs::None); adjustments.extend(autoref); @@ -155,6 +157,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, call_expr: &hir::Expr, adjusted_ty: Ty<'tcx>, + opt_arg_exprs: Option<&'gcx [hir::Expr]>, ) -> Option<(Option>, MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. for &(opt_trait_def_id, method_name, borrow) in &[ @@ -179,12 +182,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => continue, }; + let opt_input_types = opt_arg_exprs.map(|arg_exprs| [self.tcx.mk_tup( + arg_exprs + .iter() + .map(|e| self.next_ty_var( + TypeVariableOrigin::TypeInference(e.span) + )) + )]); + let opt_input_types = opt_input_types.as_ref().map(AsRef::as_ref); + if let Some(ok) = self.lookup_method_in_trait( call_expr.span, method_name, trait_def_id, adjusted_ty, - None, + opt_input_types, ) { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; @@ -445,7 +457,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> { .is_some()); // We may now know enough to figure out fn vs fnmut etc. - match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty) { + match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature From 84b9829d78056be03e81cdb7e49486fe0d8250e2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 8 Nov 2018 10:39:46 +0100 Subject: [PATCH 06/28] Move tests to ui. --- src/test/{run-pass => ui}/issue-18952.rs | 1 + src/test/{run-pass => ui}/issue-45510.rs | 1 + 2 files changed, 2 insertions(+) rename src/test/{run-pass => ui}/issue-18952.rs (99%) rename src/test/{run-pass => ui}/issue-45510.rs (97%) diff --git a/src/test/run-pass/issue-18952.rs b/src/test/ui/issue-18952.rs similarity index 99% rename from src/test/run-pass/issue-18952.rs rename to src/test/ui/issue-18952.rs index ca2645ca9e5d9..08e48c232c91e 100644 --- a/src/test/run-pass/issue-18952.rs +++ b/src/test/ui/issue-18952.rs @@ -1,4 +1,5 @@ // This issue tests fn_traits overloading on arity. +// run-pass #![feature(fn_traits)] #![feature(unboxed_closures)] diff --git a/src/test/run-pass/issue-45510.rs b/src/test/ui/issue-45510.rs similarity index 97% rename from src/test/run-pass/issue-45510.rs rename to src/test/ui/issue-45510.rs index 922a26b903094..2fa1ee813c308 100644 --- a/src/test/run-pass/issue-45510.rs +++ b/src/test/ui/issue-45510.rs @@ -1,4 +1,5 @@ // Test overloaded resolution of fn_traits. +// run-pass #![feature(fn_traits)] #![feature(unboxed_closures)] From 60df6d37c53779d555d5ef95f285c551ca81bb9a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Nov 2018 10:10:16 +0100 Subject: [PATCH 07/28] Fix failing diagnostic test. --- src/librustc_typeck/check/callee.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 5a79bec4dd72d..f10985a4d0eaa 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -145,6 +145,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) + .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None)) .map(|(autoref, method)| { let mut adjustments = autoderef.adjust_steps(self, Needs::None); adjustments.extend(autoref); From ca832a6a6a1eda58143da22006debd100929004e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Nov 2018 10:10:35 +0100 Subject: [PATCH 08/28] Add comment. --- src/librustc_typeck/check/callee.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index f10985a4d0eaa..c59c143f74b62 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -144,6 +144,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } + // Now, we look for the implementation of a Fn trait on the object's type. + // We first do it with the explicit instruction to look for an impl of + // `Fn`, with the tuple `Tuple` having an arity corresponding + // to the number of call parameters. + // If that fails (or_else branch), we try again without specifying the + // shape of the tuple (hence the None). This allows to detect an Fn trait + // is implemented, and use this information for diagnostic. self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None)) .map(|(autoref, method)| { From 1a6e594b85b1f22cc1699a539d4cd5ae752472e9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 27 Nov 2018 15:15:27 +0100 Subject: [PATCH 09/28] Change return types and check return values in tests. This allows to verify that we handle different types as return types, and that we call the expected functions. --- src/test/{ui => run-pass}/issue-18952.rs | 13 ++++++++++--- src/test/{ui => run-pass}/issue-45510.rs | 16 ++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) rename src/test/{ui => run-pass}/issue-18952.rs (75%) rename src/test/{ui => run-pass}/issue-45510.rs (59%) diff --git a/src/test/ui/issue-18952.rs b/src/test/run-pass/issue-18952.rs similarity index 75% rename from src/test/ui/issue-18952.rs rename to src/test/run-pass/issue-18952.rs index 08e48c232c91e..56378b59e3642 100644 --- a/src/test/ui/issue-18952.rs +++ b/src/test/run-pass/issue-18952.rs @@ -9,41 +9,48 @@ struct Foo; impl Fn<(isize, isize)> for Foo { extern "rust-call" fn call(&self, args: (isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 1, args.1 + 1) } } impl FnMut<(isize, isize)> for Foo { extern "rust-call" fn call_mut(&mut self, args: (isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 1, args.1 + 1) } } impl FnOnce<(isize, isize)> for Foo { - type Output = (); + type Output = (isize, isize); extern "rust-call" fn call_once(self, args: (isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 1, args.1 + 1) } } impl Fn<(isize, isize, isize)> for Foo { extern "rust-call" fn call(&self, args: (isize, isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) } } impl FnMut<(isize, isize, isize)> for Foo { extern "rust-call" fn call_mut(&mut self, args: (isize, isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) } } impl FnOnce<(isize, isize, isize)> for Foo { - type Output = (); + type Output = (isize, isize, isize); extern "rust-call" fn call_once(self, args: (isize, isize, isize)) -> Self::Output { println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) } } fn main() { let foo = Foo; - foo(1, 1); + assert_eq!(foo(1, 1), (2, 2)); + assert_eq!(foo(1, 1, 1), (4, 4, 4)); } diff --git a/src/test/ui/issue-45510.rs b/src/test/run-pass/issue-45510.rs similarity index 59% rename from src/test/ui/issue-45510.rs rename to src/test/run-pass/issue-45510.rs index 2fa1ee813c308..9e104ce6c4f30 100644 --- a/src/test/ui/issue-45510.rs +++ b/src/test/run-pass/issue-45510.rs @@ -4,25 +4,29 @@ #![feature(fn_traits)] #![feature(unboxed_closures)] +#[derive(Debug, PartialEq, Eq)] struct Ishmael; +#[derive(Debug, PartialEq, Eq)] struct Maybe; struct CallMe; impl FnOnce<(Ishmael,)> for CallMe { - type Output = (); - extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> () { + type Output = Ishmael; + extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> Ishmael { println!("Split your lungs with blood and thunder!"); + Ishmael } } impl FnOnce<(Maybe,)> for CallMe { - type Output = (); - extern "rust-call" fn call_once(self, _args: (Maybe,)) -> () { + type Output = Maybe; + extern "rust-call" fn call_once(self, _args: (Maybe,)) -> Maybe { println!("So we just met, and this is crazy"); + Maybe } } fn main() { - CallMe(Ishmael); - CallMe(Maybe); + assert_eq!(CallMe(Ishmael), Ishmael); + assert_eq!(CallMe(Maybe), Maybe); } From 093586b703a3a4776f8e6fcd20910c68efae2429 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 14 Nov 2018 22:24:22 +0000 Subject: [PATCH 10/28] Display `impl Sized` correctly It used to display as just `impl` --- src/librustc/util/ppaux.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 79405b124001d..34fea495aa64b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1325,6 +1325,8 @@ define_print! { } if !is_sized { write!(f, "{}?Sized", if first { " " } else { "+" })?; + } else if first { + write!(f, " Sized")?; } Ok(()) }) From c17597a428ff6d3fc8866048af6e82df4cc7f96f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 18 Nov 2018 18:33:44 +0000 Subject: [PATCH 11/28] Forbid impl Trait from referring to unnamable recursive types There is no type T, such that `T = [T; 2]`, we should not allow this to be circumvented by impl Trait. --- src/librustc/ty/util.rs | 74 ++++++++++- src/librustc_typeck/check/mod.rs | 32 ++++- src/librustc_typeck/diagnostics.rs | 15 +++ .../infinite-impl-trait-issue-38064.rs | 6 +- .../infinite-impl-trait-issue-38064.stderr | 20 ++- .../impl-trait/recursive-impl-trait-type.rs | 81 ++++++++++++ .../recursive-impl-trait-type.stderr | 123 ++++++++++++++++++ 7 files changed, 340 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type.stderr diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ac062a2378611..e989ef823e979 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -7,7 +7,7 @@ use hir::{self, Node}; use ich::NodeIdHashingMode; use traits::{self, ObligationCause}; use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; -use ty::subst::{Substs, UnpackedKind}; +use ty::subst::{Subst, Substs, UnpackedKind}; use ty::query::TyCtxtAt; use ty::TyKind::*; use ty::layout::{Integer, IntegerExt}; @@ -15,7 +15,7 @@ use util::common::ErrorReported; use middle::lang_items; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use std::{cmp, fmt}; use syntax::ast; use syntax::attr::{self, SignedInt, UnsignedInt}; @@ -618,6 +618,76 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } } + + /// Expands the given impl trait type, stopping if the type is recursive. + pub fn try_expand_impl_trait_type( + self, + def_id: DefId, + substs: &'tcx Substs<'tcx>, + ) -> Result, Ty<'tcx>> { + use crate::ty::fold::TypeFolder; + + struct OpaqueTypeExpander<'a, 'gcx, 'tcx> { + // Contains the DefIds of the opaque types that are currently being + // expanded. When we expand an opaque type we insert the DefId of + // that type, and when we finish expanding that type we remove the + // its DefId. + seen_opaque_tys: FxHashSet, + primary_def_id: DefId, + found_recursion: bool, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + } + + impl<'a, 'gcx, 'tcx> OpaqueTypeExpander<'a, 'gcx, 'tcx> { + fn expand_opaque_ty( + &mut self, + def_id: DefId, + substs: &'tcx Substs<'tcx>, + ) -> Option> { + if self.found_recursion { + None + } else if self.seen_opaque_tys.insert(def_id) { + let generic_ty = self.tcx.type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx, substs); + let expanded_ty = self.fold_ty(concrete_ty); + self.seen_opaque_tys.remove(&def_id); + Some(expanded_ty) + } else { + // If another opaque type that we contain is recursive, then it + // will report the error, so we don't have to. + self.found_recursion = def_id == self.primary_def_id; + None + } + } + } + + impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpaqueTypeExpander<'a, 'gcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if let ty::Opaque(def_id, substs) = t.sty { + self.expand_opaque_ty(def_id, substs).unwrap_or(t) + } else { + t.super_fold_with(self) + } + } + } + + let mut visitor = OpaqueTypeExpander { + seen_opaque_tys: FxHashSet::default(), + primary_def_id: def_id, + found_recursion: false, + tcx: self, + }; + let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap(); + if visitor.found_recursion { + Err(expanded_type) + } else { + Ok(expanded_type) + } + } } impl<'a, 'tcx> ty::TyS<'tcx> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d78d7273a36e6..8262c30679693 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1305,6 +1305,27 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_packed(tcx, span, def_id); } +fn check_opaque<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>, + span: Span, +) { + if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) { + let mut err = struct_span_err!( + tcx.sess, span, E0720, + "opaque type expands to a recursive type", + ); + err.span_label(span, "expands to self-referential type"); + if let ty::Opaque(..) = partially_expanded_type.sty { + err.note("type resolves to itself"); + } else { + err.note(&format!("expanded type is `{}`", partially_expanded_type)); + } + err.emit(); + } +} + pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) { debug!( "check_item_type(it.id={}, it.name={})", @@ -1351,7 +1372,16 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite hir::ItemKind::Union(..) => { check_union(tcx, it.id, it.span); } - hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { + hir::ItemKind::Existential(..) => { + let def_id = tcx.hir().local_def_id(it.id); + let pty_ty = tcx.type_of(def_id); + let generics = tcx.generics_of(def_id); + + check_bounds_are_used(tcx, &generics, pty_ty); + let substs = Substs::identity_for_item(tcx, def_id); + check_opaque(tcx, def_id, substs, it.span); + } + hir::ItemKind::Ty(..) => { let def_id = tcx.hir().local_def_id(it.id); let pty_ty = tcx.type_of(def_id); let generics = tcx.generics_of(def_id); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5910a8b3110d0..387dabe747ab8 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4816,6 +4816,21 @@ type, it's not allowed to override anything in those implementations, as it would be ambiguous which override should actually be used. "##, + +E0720: r##" +An `impl Trait` type expands to a recursive type. + +An `impl Trait` type must be expandable to a concrete type that contains no +`impl Trait` types. For example the following example tries to create an +`impl Trait` type `T` that is equal to `[T, T]`: + +```compile_fail,E0720 +fn make_recursive_type() -> impl Sized { + [make_recursive_type(), make_recursive_type()] +} +``` +"##, + } register_diagnostics! { diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs index c84e5883bb2a5..150a8015cbc75 100644 --- a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs +++ b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.rs @@ -3,17 +3,15 @@ // // Regression test for #38064. -// error-pattern:overflow evaluating the requirement `impl Quux` - trait Quux {} -fn foo() -> impl Quux { +fn foo() -> impl Quux { //~ opaque type expands to a recursive type struct Foo(T); impl Quux for Foo {} Foo(bar()) } -fn bar() -> impl Quux { +fn bar() -> impl Quux { //~ opaque type expands to a recursive type struct Bar(T); impl Quux for Bar {} Bar(foo()) diff --git a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr index f260cce647bd2..99c8fe35c66d0 100644 --- a/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr +++ b/src/test/ui/impl-trait/infinite-impl-trait-issue-38064.stderr @@ -1,7 +1,19 @@ -error[E0275]: overflow evaluating the requirement `impl Quux` +error[E0720]: opaque type expands to a recursive type + --> $DIR/infinite-impl-trait-issue-38064.rs:8:13 | - = help: consider adding a `#![recursion_limit="128"]` attribute to your crate +LL | fn foo() -> impl Quux { //~ opaque type expands to a recursive type + | ^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `foo::Foo>` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/infinite-impl-trait-issue-38064.rs:14:13 + | +LL | fn bar() -> impl Quux { //~ opaque type expands to a recursive type + | ^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `bar::Bar>` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs new file mode 100644 index 0000000000000..facb191a37081 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs @@ -0,0 +1,81 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. + +#![feature(await_macro, async_await, futures_api, generators)] + +fn option(i: i32) -> impl Sized { //~ ERROR + if i < 0 { + None + } else { + Some((option(i - 1), i)) + } +} + +fn tuple() -> impl Sized { //~ ERROR + (tuple(),) +} + +fn array() -> impl Sized { //~ ERROR + [array()] +} + +fn ptr() -> impl Sized { //~ ERROR + &ptr() as *const _ +} + +fn fn_ptr() -> impl Sized { //~ ERROR + fn_ptr as fn() -> _ +} + +fn closure_capture() -> impl Sized { //~ ERROR + let x = closure_capture(); + move || { x; } +} + +fn closure_ref_capture() -> impl Sized { //~ ERROR + let x = closure_ref_capture(); + move || { &x; } +} + +fn closure_sig() -> impl Sized { //~ ERROR + || closure_sig() +} + +fn generator_sig() -> impl Sized { //~ ERROR + || generator_sig() +} + +fn generator_capture() -> impl Sized { //~ ERROR + let x = generator_capture(); + move || { yield; x; } +} + +fn substs_change() -> impl Sized { //~ ERROR + (substs_change::<&T>(),) +} + +fn generator_hold() -> impl Sized { //~ ERROR + move || { + let x = generator_hold(); + yield; + x; + } +} + +async fn recursive_async_function() -> () { //~ ERROR + await!(recursive_async_function()); +} + +fn use_fn_ptr() -> impl Sized { // OK, error already reported + fn_ptr() +} + +fn mutual_recursion() -> impl Sync { //~ ERROR + mutual_recursion_b() +} + +fn mutual_recursion_b() -> impl Sized { //~ ERROR + mutual_recursion() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr new file mode 100644 index 0000000000000..8a8789120577e --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr @@ -0,0 +1,123 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:6:22 + | +LL | fn option(i: i32) -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `std::option::Option<(impl Sized, i32)>` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:14:15 + | +LL | fn tuple() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `(impl Sized,)` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:18:15 + | +LL | fn array() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[impl Sized; 1]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:22:13 + | +LL | fn ptr() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `*const impl Sized` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:26:16 + | +LL | fn fn_ptr() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `fn() -> impl Sized` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:30:25 + | +LL | fn closure_capture() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:32:5: 32:19 x:impl Sized]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:35:29 + | +LL | fn closure_ref_capture() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:37:5: 37:20 x:impl Sized]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:40:21 + | +LL | fn closure_sig() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:41:5: 41:21]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:44:23 + | +LL | fn generator_sig() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:45:5: 45:23]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:48:27 + | +LL | fn generator_capture() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:50:5: 50:26 x:impl Sized {()}]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:53:26 + | +LL | fn substs_change() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `(impl Sized,)` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:57:24 + | +LL | fn generator_hold() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:65:40 + | +LL | async fn recursive_async_function() -> () { //~ ERROR + | ^^ expands to self-referential type + | + = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>` + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:73:26 + | +LL | fn mutual_recursion() -> impl Sync { //~ ERROR + | ^^^^^^^^^ expands to self-referential type + | + = note: type resolves to itself + +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type.rs:77:28 + | +LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR + | ^^^^^^^^^^ expands to self-referential type + | + = note: type resolves to itself + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0720`. From 359795f671448ee948a5a314259fec76691efc16 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 11 Dec 2018 19:56:59 +0100 Subject: [PATCH 12/28] Move the `Unevaluated` constant arm upwards in the type structure --- src/librustc/ich/impls_ty.rs | 6 +- src/librustc/mir/interpret/value.rs | 10 +-- src/librustc/mir/mod.rs | 16 +++- src/librustc/mir/tcx.rs | 2 +- src/librustc/mir/visit.rs | 4 +- src/librustc/traits/error_reporting.rs | 26 ++++--- src/librustc/traits/project.rs | 12 +-- src/librustc/traits/query/normalize.rs | 13 ++-- src/librustc/ty/codec.rs | 16 ++++ src/librustc/ty/context.rs | 25 ++++++- src/librustc/ty/error.rs | 7 +- src/librustc/ty/flags.rs | 14 +--- src/librustc/ty/fold.rs | 9 +-- src/librustc/ty/inhabitedness/mod.rs | 15 ++-- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/relate.rs | 22 ++---- src/librustc/ty/structural_impls.rs | 38 +++++----- src/librustc/ty/sty.rs | 45 +++++++---- src/librustc/ty/walk.rs | 12 +-- src/librustc/ty/wf.rs | 11 +-- src/librustc/util/ppaux.rs | 9 +-- .../debuginfo/metadata.rs | 2 +- .../debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_codegen_ssa/mir/constant.rs | 12 +-- src/librustc_codegen_ssa/mir/operand.rs | 1 - src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- .../borrow_check/error_reporting.rs | 5 +- .../borrow_check/mutability_errors.rs | 4 +- src/librustc_mir/borrow_check/nll/renumber.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 15 ++-- .../borrow_check/places_conflict.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 12 +-- src/librustc_mir/build/matches/test.rs | 1 + src/librustc_mir/build/misc.rs | 2 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/const_eval.rs | 12 +-- src/librustc_mir/hair/cx/expr.rs | 39 +++++----- src/librustc_mir/hair/cx/mod.rs | 12 +-- src/librustc_mir/hair/mod.rs | 4 +- src/librustc_mir/hair/pattern/_match.rs | 38 +++++----- src/librustc_mir/hair/pattern/mod.rs | 4 +- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/interpret/operand.rs | 19 +++-- src/librustc_mir/monomorphize/collector.rs | 75 ++++++++++--------- src/librustc_mir/monomorphize/item.rs | 2 +- src/librustc_mir/shim.rs | 14 +++- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 4 +- src/librustc_mir/transform/erase_regions.rs | 2 +- src/librustc_mir/transform/generator.rs | 8 +- src/librustc_mir/transform/qualify_consts.rs | 14 ++-- .../transform/simplify_branches.rs | 25 ++++--- .../transform/uniform_array_move_out.rs | 4 +- src/librustc_mir/util/elaborate_drops.rs | 6 +- src/librustc_mir/util/pretty.rs | 19 +++-- .../chalk_context/program_clauses.rs | 2 +- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustdoc/clean/mod.rs | 23 +++--- 62 files changed, 405 insertions(+), 316 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index b2fe4b7561c5a..57a53d3f09a2e 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -301,7 +301,6 @@ impl_stable_hash_for!(struct ty::FieldDef { impl_stable_hash_for!( impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] { - Unevaluated(def_id, substs), Scalar(val), ScalarPair(a, b), ByRef(id, alloc, offset), @@ -378,6 +377,11 @@ impl_stable_hash_for!(struct ty::Const<'tcx> { val }); +impl_stable_hash_for!(impl<'tcx> for enum ty::LazyConst<'tcx> [ty::LazyConst] { + Unevaluated(did, substs), + Evaluated(c) +}); + impl_stable_hash_for!(enum mir::interpret::ErrorHandled { Reported, TooGeneric diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 1e4cfedc2a6ae..26a8e63254008 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -1,7 +1,6 @@ use std::fmt; -use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}}; -use crate::hir::def_id::DefId; +use crate::ty::{Ty, layout::{HasDataLayout, Size}}; use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; @@ -18,12 +17,6 @@ pub struct RawConst<'tcx> { /// matches the LocalValue optimizations for easy conversions between Value and ConstValue. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] pub enum ConstValue<'tcx> { - /// Never returned from the `const_eval` query, but the HIR contains these frequently in order - /// to allow HIR creation to happen for everything before needing to be able to run constant - /// evaluation - /// FIXME: The query should then return a type that does not even have this variant. - Unevaluated(DefId, &'tcx Substs<'tcx>), - /// Used only for types with layout::abi::Scalar ABI and ZSTs /// /// Not using the enum `Value` to encode that this must not be `Undef` @@ -43,7 +36,6 @@ impl<'tcx> ConstValue<'tcx> { #[inline] pub fn try_to_scalar(&self) -> Option { match *self { - ConstValue::Unevaluated(..) | ConstValue::ByRef(..) | ConstValue::ScalarPair(..) => None, ConstValue::Scalar(val) => Some(val), diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 2936405ebd0b7..eafae6d9c9e8d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2154,7 +2154,9 @@ impl<'tcx> Operand<'tcx> { span, ty, user_ty: None, - literal: ty::Const::zero_sized(tcx, ty), + literal: tcx.intern_lazy_const( + ty::LazyConst::Evaluated(ty::Const::zero_sized(tcx, ty)), + ), }) } @@ -2457,7 +2459,7 @@ pub struct Constant<'tcx> { /// Needed for NLL to impose user-given type constraints. pub user_ty: Option, - pub literal: &'tcx ty::Const<'tcx>, + pub literal: &'tcx ty::LazyConst<'tcx>, } /// A collection of projections into user types. @@ -2655,7 +2657,15 @@ newtype_index! { impl<'tcx> Debug for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!(fmt, "const ")?; - fmt_const_val(fmt, self.literal) + fmt_lazy_const_val(fmt, self.literal) + } +} + +/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output. +pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result { + match const_val { + ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val), + ty::LazyConst::Evaluated(c) => fmt_const_val(f, c), } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index c5b884525da4b..6dda1933bbafa 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { PlaceTy::Ty { ty: match ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_usize(tcx); + let size = size.unwrap_evaluated().unwrap_usize(tcx); let len = size - (from as u64) - (to as u64); tcx.mk_array(inner, len) } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 67f85fbc8679e..a0fae3aa927ce 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -233,7 +233,7 @@ macro_rules! make_mir_visitor { } fn visit_const(&mut self, - constant: & $($mutability)* &'tcx ty::Const<'tcx>, + constant: & $($mutability)* &'tcx ty::LazyConst<'tcx>, _: Location) { self.super_const(constant); } @@ -892,7 +892,7 @@ macro_rules! make_mir_visitor { fn super_region(&mut self, _region: & $($mutability)* ty::Region<'tcx>) { } - fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::Const<'tcx>) { + fn super_const(&mut self, _const: & $($mutability)* &'tcx ty::LazyConst<'tcx>) { } fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 21352ac1053a8..df4b7c7731bb0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -418,18 +418,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(format!("[{}]", self.tcx.type_of(def.did).to_string())), )); let tcx = self.tcx; - if let Some(len) = len.val.try_to_scalar().and_then(|scalar| { - scalar.to_usize(&tcx).ok() - }) { - flags.push(( - "_Self".to_owned(), - Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), - )); - } else { - flags.push(( - "_Self".to_owned(), - Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())), - )); + if let ty::LazyConst::Evaluated(len) = len { + if let Some(len) = len.val.try_to_scalar().and_then(|scalar| { + scalar.to_usize(&tcx).ok() + }) { + flags.push(( + "_Self".to_owned(), + Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), + )); + } else { + flags.push(( + "_Self".to_owned(), + Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())), + )); + } } } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 732ca70dc78c5..bec45046cb93e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -15,7 +15,6 @@ use super::util; use hir::def_id::DefId; use infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use infer::type_variable::TypeVariableOrigin; -use mir::interpret::ConstValue; use mir::interpret::{GlobalId}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use syntax::ast::Ident; @@ -394,8 +393,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, } } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { + fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + if let ty::LazyConst::Unevaluated(def_id, substs) = *constant { let tcx = self.selcx.tcx().global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { if substs.needs_infer() || substs.has_placeholders() { @@ -407,8 +406,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); + let substs = tcx.lift_to_global(&substs).unwrap(); + let evaluated = evaluated.subst(tcx, substs); + return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } else { @@ -420,7 +420,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return self.fold_const(evaluated) + return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 0d126d37546d6..be05445cfc61a 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -5,7 +5,7 @@ use infer::at::At; use infer::canonical::OriginalQueryValues; use infer::{InferCtxt, InferOk}; -use mir::interpret::{ConstValue, GlobalId}; +use mir::interpret::GlobalId; use traits::project::Normalized; use traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use ty::fold::{TypeFoldable, TypeFolder}; @@ -188,8 +188,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx } } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { + fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + if let ty::LazyConst::Unevaluated(def_id, substs) = *constant { let tcx = self.infcx.tcx.global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { if substs.needs_infer() || substs.has_placeholders() { @@ -201,8 +201,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - let evaluated = evaluated.subst(self.tcx(), substs); - return self.fold_const(evaluated); + let substs = tcx.lift_to_global(&substs).unwrap(); + let evaluated = evaluated.subst(tcx, substs); + return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } else { @@ -214,7 +215,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return self.fold_const(evaluated) + return tcx.intern_lazy_const(ty::LazyConst::Evaluated(evaluated)); } } } diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 6429e3249c4c5..57b99db0c7d54 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -255,6 +255,15 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D) Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?)) } +#[inline] +pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D) + -> Result<&'tcx ty::LazyConst<'tcx>, D::Error> + where D: TyDecoder<'a, 'tcx>, + 'tcx: 'a, +{ + Ok(decoder.tcx().intern_lazy_const(Decodable::decode(decoder)?)) +} + #[inline] pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error> @@ -396,6 +405,13 @@ macro_rules! implement_ty_decoder { } } + impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>> + for $DecoderName<$($typaram),*> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> { + decode_lazy_const(self) + } + } + impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation> for $DecoderName<$($typaram),*> { fn specialized_decode( diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 32348e2e5046d..715e7367fada7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -29,7 +29,7 @@ use traits; use traits::{Clause, Clauses, GoalKind, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TyKind, List}; -use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const}; +use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst}; use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; @@ -1112,6 +1112,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) } + pub fn intern_lazy_const(self, c: ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + self.global_interners.arena.alloc(c) + } + pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails { self.layout_interner.borrow_mut().intern(layout, |layout| { self.global_arenas.layout.alloc(layout) @@ -1814,6 +1818,21 @@ impl<'a, 'tcx> Lift<'tcx> for &'a List> { } } +impl<'a, 'tcx> Lift<'tcx> for &'a LazyConst<'a> { + type Lifted = &'tcx LazyConst<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx LazyConst<'tcx>> { + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); + } + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } + } +} + impl<'a, 'tcx> Lift<'tcx> for &'a Const<'a> { type Lifted = &'tcx Const<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Const<'tcx>> { @@ -2683,7 +2702,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty(Array(ty, ty::Const::from_usize(self, n))) + self.mk_ty(Array(ty, self.intern_lazy_const( + ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n)) + ))) } #[inline] diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 76e102d88d7ce..0d6d9f91eb4e4 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -157,11 +157,12 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(), ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(), - ty::Array(_, n) => { - match n.assert_usize(tcx) { + ty::Array(_, n) => match n { + ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) { Some(n) => format!("array of {} elements", n).into(), None => "array".into(), - } + }, + ty::LazyConst::Unevaluated(..) => "array".into(), } ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "*-ptr".into(), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6ee24187e3326..4fa13a01d5a92 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -1,4 +1,3 @@ -use mir::interpret::ConstValue; use ty::subst::Substs; use ty::{self, Ty, TypeFlags, TypeFoldable}; @@ -173,7 +172,10 @@ impl FlagComputation { &ty::Array(tt, len) => { self.add_ty(tt); - self.add_const(len); + if let ty::LazyConst::Unevaluated(_, substs) = len { + self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_substs(substs); + } } &ty::Slice(tt) => { @@ -230,14 +232,6 @@ impl FlagComputation { } } - fn add_const(&mut self, constant: &ty::Const<'_>) { - self.add_ty(constant.ty); - if let ConstValue::Unevaluated(_, substs) = constant.val { - self.add_flags(TypeFlags::HAS_PROJECTION); - self.add_substs(substs); - } - } - fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); self.add_ty(projection.ty); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 0a72f733b51e5..4495e9654c984 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -29,7 +29,6 @@ //! These methods return true to indicate that the visitor has found what it is looking for //! and does not need to visit anything else. -use mir::interpret::ConstValue; use hir::def_id::DefId; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; @@ -164,7 +163,7 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { c.super_fold_with(self) } } @@ -182,7 +181,7 @@ pub trait TypeVisitor<'tcx> : Sized { r.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { + fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool { c.super_visit_with(self) } } @@ -864,8 +863,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { flags.intersects(self.flags) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { - if let ConstValue::Unevaluated(..) = c.val { + fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool { + if let ty::LazyConst::Unevaluated(..) = c { let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION; if projection_flags.intersects(self.flags) { diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 29d201c1179e5..6dfc9681cfd86 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -1,6 +1,6 @@ use ty::context::TyCtxt; use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; -use ty::{DefId, Substs}; +use ty::{self, DefId, Substs}; use ty::{AdtKind, Visibility}; use ty::TyKind::*; @@ -213,11 +213,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } Array(ty, len) => { - match len.assert_usize(tcx) { - // If the array is definitely non-empty, it's uninhabited if - // the type of its elements is uninhabited. - Some(n) if n != 0 => ty.uninhabited_from(tcx), - _ => DefIdForest::empty() + match len { + ty::LazyConst::Unevaluated(..) => DefIdForest::empty(), + ty::LazyConst::Evaluated(len) => match len.assert_usize(tcx) { + // If the array is definitely non-empty, it's uninhabited if + // the type of its elements is uninhabited. + Some(n) if n != 0 => ty.uninhabited_from(tcx), + _ => DefIdForest::empty() + }, } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 171c53b7b20ba..1f25925a8e1d1 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -543,7 +543,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } let element = self.layout_of(element)?; - let count = count.unwrap_usize(tcx); + let count = count.unwrap_evaluated().unwrap_usize(tcx); let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d40dd830e9fb9..20167bd41fb87 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -59,7 +59,7 @@ pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TyKind, PolyTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; -pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; +pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::RegionKind; pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid}; diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 84e15a751353e..6d310a9500a62 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -5,7 +5,6 @@ //! subtyping, type equality, etc. use hir::def_id::DefId; -use mir::interpret::ConstValue; use ty::subst::{Kind, UnpackedKind, Substs}; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; @@ -480,14 +479,9 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(&a_t, &b_t)?; - assert_eq!(sz_a.ty, tcx.types.usize); - assert_eq!(sz_b.ty, tcx.types.usize); - let to_u64 = |x: &'tcx ty::Const<'tcx>| -> Result { - if let Some(s) = x.assert_usize(tcx) { - return Ok(s); - } - match x.val { - ConstValue::Unevaluated(def_id, substs) => { + let to_u64 = |x: ty::LazyConst<'tcx>| -> Result { + match x { + ty::LazyConst::Unevaluated(def_id, substs) => { // FIXME(eddyb) get the right param_env. let param_env = ty::ParamEnv::empty(); if let Some(substs) = tcx.lift_to_global(&substs) { @@ -513,14 +507,14 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, "array length could not be evaluated"); Err(ErrorReported) } - _ => { + ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| { tcx.sess.delay_span_bug(DUMMY_SP, - &format!("arrays should not have {:?} as length", x)); - Err(ErrorReported) - } + "array length could not be evaluated"); + ErrorReported + }) } }; - match (to_u64(sz_a), to_u64(sz_b)) { + match (to_u64(*sz_a), to_u64(*sz_b)) { (Ok(sz_a_u64), Ok(sz_b_u64)) => { if sz_a_u64 == sz_b_u64 { Ok(tcx.mk_ty(ty::Array(t, sz_a))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f9b43f42d5298..b4af81ab69d8b 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -53,6 +53,7 @@ CloneTypeFoldableAndLiftImpls! { ::ty::UniverseIndex, ::ty::Variance, ::syntax_pos::Span, + ConstValue<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -1014,26 +1015,31 @@ EnumTypeFoldableImpl! { } } -impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - ConstValue::Scalar(v) => ConstValue::Scalar(v), - ConstValue::ScalarPair(a, b) => ConstValue::ScalarPair(a, b), - ConstValue::ByRef(id, alloc, offset) => ConstValue::ByRef(id, alloc, offset), - ConstValue::Unevaluated(def_id, substs) => { - ConstValue::Unevaluated(def_id, substs.fold_with(folder)) + let new = match self { + ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)), + ty::LazyConst::Unevaluated(def_id, substs) => { + ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder)) } - } + }; + folder.tcx().intern_lazy_const(new) + } + + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + folder.fold_const(*self) } fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - ConstValue::Scalar(_) | - ConstValue::ScalarPair(_, _) | - ConstValue::ByRef(_, _, _) => false, - ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), + ty::LazyConst::Evaluated(c) => c.visit_with(visitor), + ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor), } } + + fn visit_with>(&self, visitor: &mut V) -> bool { + visitor.visit_const(self) + } } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { @@ -1046,15 +1052,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { }) } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_const(*self) - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { self.ty.visit_with(visitor) || self.val.visit_with(visitor) } - - fn visit_with>(&self, visitor: &mut V) -> bool { - visitor.visit_const(self) - } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a2720bdf385cd..6a9a9fd0ed17c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -113,7 +113,7 @@ pub enum TyKind<'tcx> { Str, /// An array with the given length. Written as `[T; n]`. - Array(Ty<'tcx>, &'tcx ty::Const<'tcx>), + Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>), /// The pointee of an array slice. Written as `[T]`. Slice(Ty<'tcx>), @@ -2020,6 +2020,36 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } +#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] +/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the +/// code is monomorphic enough for that. +pub enum LazyConst<'tcx> { + Unevaluated(DefId, &'tcx Substs<'tcx>), + Evaluated(&'tcx Const<'tcx>), +} + +static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::>() == 24); + +impl<'tcx> LazyConst<'tcx> { + pub fn unwrap_evaluated(self) -> &'tcx Const<'tcx> { + match self { + LazyConst::Evaluated(c) => c, + LazyConst::Unevaluated(..) => bug!("unexpected unevaluated constant"), + } + } + + pub fn map_evaluated(self, f: impl FnOnce(&'tcx Const<'tcx>) -> Option) -> Option { + match self { + LazyConst::Evaluated(c) => f(c), + LazyConst::Unevaluated(..) => None, + } + } + + pub fn assert_usize(self, tcx: TyCtxt<'_, '_, 'tcx>) -> Option { + self.map_evaluated(|c| c.assert_usize(tcx)) + } +} + /// Typed constant value. #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] pub struct Const<'tcx> { @@ -2029,18 +2059,6 @@ pub struct Const<'tcx> { } impl<'tcx> Const<'tcx> { - pub fn unevaluated( - tcx: TyCtxt<'_, '_, 'tcx>, - def_id: DefId, - substs: &'tcx Substs<'tcx>, - ty: Ty<'tcx>, - ) -> &'tcx Self { - tcx.mk_const(Const { - val: ConstValue::Unevaluated(def_id, substs), - ty, - }) - } - #[inline] pub fn from_const_value( tcx: TyCtxt<'_, '_, 'tcx>, @@ -2156,3 +2174,4 @@ impl<'tcx> Const<'tcx> { } impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {} diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index a2cc859e4a82d..6887d092fcd62 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -1,7 +1,6 @@ //! An iterator over the type substructure. //! WARNING: this does not keep track of the region depth. -use mir::interpret::ConstValue; use ty::{self, Ty}; use smallvec::{self, SmallVec}; @@ -75,7 +74,9 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => { } ty::Array(ty, len) => { - push_const(stack, len); + if let ty::LazyConst::Unevaluated(_, substs) = len { + stack.extend(substs.types().rev()); + } stack.push(ty); } ty::Slice(ty) => { @@ -128,10 +129,3 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { } } } - -fn push_const<'tcx>(stack: &mut TypeWalkerStack<'tcx>, constant: &'tcx ty::Const<'tcx>) { - if let ConstValue::Unevaluated(_, substs) = constant.val { - stack.extend(substs.types().rev()); - } - stack.push(constant.ty); -} diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index aacc63c47de61..517cfd9edfaf9 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -1,5 +1,4 @@ use hir::def_id::DefId; -use mir::interpret::ConstValue; use infer::InferCtxt; use ty::subst::Substs; use traits; @@ -202,11 +201,10 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - /// Pushes the obligations required for a constant value to be WF + /// Pushes the obligations required for an array length to be WF /// into `self.out`. - fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) { - self.require_sized(constant.ty, traits::ConstSized); - if let ConstValue::Unevaluated(def_id, substs) = constant.val { + fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) { + if let ty::LazyConst::Unevaluated(def_id, substs) = constant { let obligations = self.nominal_obligations(def_id, substs); self.out.extend(obligations); @@ -260,8 +258,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::Array(subty, len) => { self.require_sized(subty, traits::SliceOrArrayElem); - assert_eq!(len.ty, self.infcx.tcx.types.usize); - self.compute_const(len); + self.compute_array_len(*len); } ty::Tuple(ref tys) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 34fea495aa64b..37bc9397d904b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,6 +1,5 @@ use hir::def_id::DefId; use hir::map::definitions::DefPathData; -use mir::interpret::ConstValue; use middle::region; use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; @@ -1412,12 +1411,12 @@ define_print! { }), Array(ty, sz) => { print!(f, cx, write("["), print(ty), write("; "))?; - match sz.val { - ConstValue::Unevaluated(_def_id, _substs) => { + match sz { + ty::LazyConst::Unevaluated(_def_id, _substs) => { write!(f, "_")?; } - _ => ty::tls::with(|tcx| { - write!(f, "{}", sz.unwrap_usize(tcx)) + ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| { + write!(f, "{}", c.unwrap_usize(tcx)) })?, } write!(f, "]") diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0fd04e9d20393..bec0cfa0d862f 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -302,7 +302,7 @@ fn fixed_vec_metadata( let upper_bound = match array_or_slice_type.sty { ty::Array(_, len) => { - len.unwrap_usize(cx.tcx) as c_longlong + len.unwrap_evaluated().unwrap_usize(cx.tcx) as c_longlong } _ => -1 }; diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index c8cbd735e850d..c1309569c7955 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -88,7 +88,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); - output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx))); + output.push_str(&format!("; {}", len.unwrap_evaluated().unwrap_usize(cx.tcx))); output.push(']'); }, ty::Slice(inner_type) => { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index b88ec075653ba..166655f6a8061 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -171,7 +171,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( let (source, target) = cx.tcx().struct_lockstep_tails(source, target); match (&source.sty, &target.sty) { (&ty::Array(_, len), &ty::Slice(_)) => { - cx.const_usize(len.unwrap_usize(cx.tcx())) + cx.const_usize(len.unwrap_evaluated().unwrap_usize(cx.tcx())) } (&ty::Dynamic(..), &ty::Dynamic(..)) => { // For now, upcasts are limited to changes in marker diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 1a48ad87a6e15..58325e3443266 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -2,7 +2,7 @@ use rustc::mir::interpret::ErrorHandled; use rustc_mir::const_eval::const_field; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; -use rustc::mir::interpret::{GlobalId, ConstValue}; +use rustc::mir::interpret::GlobalId; use rustc::ty::{self, Ty}; use rustc::ty::layout; use syntax::source_map::Span; @@ -14,10 +14,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn fully_evaluate( &mut self, bx: &Bx, - constant: &'tcx ty::Const<'tcx>, + constant: &'tcx ty::LazyConst<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { - match constant.val { - ConstValue::Unevaluated(def_id, ref substs) => { + match *constant { + ty::LazyConst::Unevaluated(def_id, ref substs) => { let tcx = bx.tcx(); let param_env = ty::ParamEnv::reveal_all(); let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap(); @@ -27,7 +27,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; tcx.const_eval(param_env.and(cid)) }, - _ => Ok(constant), + ty::LazyConst::Evaluated(constant) => Ok(constant), } } @@ -52,7 +52,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .and_then(|c| { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { - ty::Array(_, n) => n.unwrap_usize(bx.tcx()), + ty::Array(_, n) => n.unwrap_evaluated().unwrap_usize(bx.tcx()), ref other => bug!("invalid simd shuffle type: {}", other), }; let values: Result, ErrorHandled> = (0..fields).map(|field| { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 1dbed30842a82..bb55bf3b46cd4 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -76,7 +76,6 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { } let val = match val.val { - ConstValue::Unevaluated(..) => bug!(), ConstValue::Scalar(x) => { let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9ca5414fa717e..404ee86c6a117 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -537,7 +537,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let mir::Place::Local(index) = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.sty { - let n = n.unwrap_usize(bx.cx().tcx()); + let n = n.unwrap_evaluated().unwrap_usize(bx.cx().tcx()); return bx.cx().const_usize(n); } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 83cd28bbdc58c..ad8abe16415ed 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1380,7 +1380,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); if let TerminatorKind::Call { func: Operand::Constant(box Constant { - literal: ty::Const { ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), .. }, .. }, + literal: ty::LazyConst::Evaluated(ty::Const { + ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), .. }, + .. + }), .. }), args, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 0be8ecffcdf38..63bf6faed40d4 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -468,13 +468,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { Terminator { kind: TerminatorKind::Call { func: Operand::Constant(box Constant { - literal: Const { + literal: ty::LazyConst::Evaluated(Const { ty: &TyS { sty: TyKind::FnDef(id, substs), .. }, .. - }, + }), .. }), .. diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 55af7399aab8f..5c24da7621b2d 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_region: region={:?}", region); } - fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) { + fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) { *constant = self.renumber_regions(&*constant); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b3e1237a45087..3b49b8a74f769 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -382,6 +382,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { constant, location ); + let literal = match constant.literal { + ty::LazyConst::Evaluated(lit) => lit, + ty::LazyConst::Unevaluated(..) => return, + }; + // FIXME(#46702) -- We need some way to get the predicates // associated with the "pre-evaluated" form of the // constant. For example, consider that the constant @@ -390,7 +395,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { // constraints on `'a` and `'b`. These constraints // would be lost if we just look at the normalized // value. - if let ty::FnDef(def_id, substs) = constant.literal.ty.sty { + if let ty::FnDef(def_id, substs) = literal.ty.sty { let tcx = self.tcx(); let type_checker = &mut self.cx; @@ -411,10 +416,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ); } - debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty); + debug!("sanitize_constant: expected_ty={:?}", literal.ty); if let Err(terr) = self.cx.eq_types( - constant.literal.ty, + literal.ty, constant.ty, location.to_locations(), ConstraintCategory::Boring, @@ -424,7 +429,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { constant, "constant {:?} should have type {:?} but has {:?} ({:?})", constant, - constant.literal.ty, + literal.ty, constant.ty, terr, ); @@ -567,7 +572,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ProjectionElem::Subslice { from, to } => PlaceTy::Ty { ty: match base_ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_usize(tcx); + let size = size.unwrap_evaluated().unwrap_usize(tcx); let min_size = (from as u64) + (to as u64); if let Some(rest_size) = size.checked_sub(min_size) { tcx.mk_array(inner, rest_size) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index ac7182abb36da..88c27a869c089 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -388,7 +388,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( (Place::Promoted(p1), Place::Promoted(p2)) => { if p1.0 == p2.0 { if let ty::Array(_, size) = p1.1.sty { - if size.unwrap_usize(tcx) == 0 { + if size.unwrap_evaluated().unwrap_usize(tcx) == 0 { // Ignore conflicts with promoted [T; 0]. debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); return Overlap::Disjoint; diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7dcac05e702a3..a66da50c48437 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -270,11 +270,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: expr_span, ty: this.hir.tcx().types.u32, user_ty: None, - literal: ty::Const::from_bits( - this.hir.tcx(), - 0, - ty::ParamEnv::empty().and(this.hir.tcx().types.u32), - ), + literal: this.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::from_bits( + this.hir.tcx(), + 0, + ty::ParamEnv::empty().and(this.hir.tcx().types.u32), + ), + )), })); box AggregateKind::Generator(closure_id, substs, movability) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 21109a223bf77..f601e38717f2d 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -302,6 +302,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap(); let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]); + let method = self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(method)); // take the argument by reference let region_scope = self.topmost_scope(); diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 5b20d412f0dd5..9745fe392b652 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -33,7 +33,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span, ty, user_ty: None, - literal, + literal: self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(literal)), }; Operand::Constant(constant) } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8acdecf6fa248..727b769cf4d44 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -202,7 +202,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> { } } - fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { + fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) { if let Some(lifted) = self.tcx.lift(constant) { *constant = lifted; } else { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index b9432997b7e19..58a0f13733ea8 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -136,12 +136,14 @@ pub fn op_to_const<'tcx>( }; Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) } + pub fn const_to_op<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, - cnst: &ty::Const<'tcx>, + cnst: ty::LazyConst<'tcx>, + ty: ty::Ty<'tcx>, ) -> EvalResult<'tcx, OpTy<'tcx>> { - let op = ecx.const_value_to_op(cnst.val)?; - Ok(OpTy { op, layout: ecx.layout_of(cnst.ty)? }) + let op = ecx.const_value_to_op(cnst)?; + Ok(OpTy { op, layout: ecx.layout_of(ty)? }) } fn eval_body_and_ecx<'a, 'mir, 'tcx>( @@ -514,7 +516,7 @@ pub fn const_field<'a, 'tcx>( let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let result = (|| { // get the operand again - let op = const_to_op(&ecx, value)?; + let op = const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?; // downcast let down = match variant { None => op, @@ -541,7 +543,7 @@ pub fn const_variant_index<'a, 'tcx>( ) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}, {:?}", instance, val); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); - let op = const_to_op(&ecx, val)?; + let op = const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?; Ok(ecx.read_discriminant(op)?.1) } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 293058a0f26f5..e2d0f6b0ae625 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -356,7 +356,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprKind::Lit(ref lit) => ExprKind::Literal { - literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false), + literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + cx.const_eval_literal(&lit.node, expr_ty, lit.span, false) + )), user_ty: None, }, @@ -454,7 +456,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } else { if let hir::ExprKind::Lit(ref lit) = arg.node { ExprKind::Literal { - literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true), + literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + cx.const_eval_literal(&lit.node, expr_ty, lit.span, true) + )), user_ty: None, } } else { @@ -711,24 +715,22 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, temp_lifetime, ty: var_ty, span: expr.span, - kind: ExprKind::Literal { literal, user_ty: None }, + kind: ExprKind::Literal { + literal: cx.tcx.intern_lazy_const(literal), + user_ty: None + }, }.to_ref(); - let offset = mk_const(ty::Const::from_bits( + let offset = mk_const(ty::LazyConst::Evaluated(ty::Const::from_bits( cx.tcx, offset as u128, cx.param_env.and(var_ty), - )); + ))); match did { Some(did) => { // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) let substs = Substs::identity_for_item(cx.tcx(), did); - let lhs = mk_const(ty::Const::unevaluated( - cx.tcx(), - did, - substs, - var_ty, - )); + let lhs = mk_const(ty::LazyConst::Unevaluated(did, substs)); let bin = ExprKind::Binary { op: BinOp::Add, lhs, @@ -868,7 +870,9 @@ fn method_callee<'a, 'gcx, 'tcx>( ty, span, kind: ExprKind::Literal { - literal: ty::Const::zero_sized(cx.tcx(), ty), + literal: cx.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::zero_sized(cx.tcx(), ty) + )), user_ty, }, } @@ -928,10 +932,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { - literal: ty::Const::zero_sized( + literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized( cx.tcx, cx.tables().node_id_to_type(expr.hir_id), - ), + ))), user_ty, } }, @@ -941,12 +945,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { - literal: ty::Const::unevaluated( - cx.tcx, - def_id, - substs, - cx.tables().node_id_to_type(expr.hir_id), - ), + literal: cx.tcx.intern_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)), user_ty, } }, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 07f3c38c62c52..96ea668dd8f03 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -108,8 +108,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx.types.usize } - pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> { - ty::Const::from_usize(self.tcx, value) + pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> { + self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value))) } pub fn bool_ty(&mut self) -> Ty<'tcx> { @@ -120,12 +120,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx.mk_unit() } - pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> { - ty::Const::from_bool(self.tcx, true) + pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> { + self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true))) } - pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> { - ty::Const::from_bool(self.tcx, false) + pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> { + self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false))) } pub fn const_eval_literal( diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index b56e3d4e77395..676b98457489f 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId; use rustc::infer::canonical::Canonical; use rustc::middle::region; use rustc::ty::subst::Substs; -use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, UserTypeAnnotation}; +use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, LazyConst, UserTypeAnnotation}; use rustc::ty::layout::VariantIdx; use rustc::hir; use syntax::ast; @@ -288,7 +288,7 @@ pub enum ExprKind<'tcx> { movability: Option, }, Literal { - literal: &'tcx Const<'tcx>, + literal: &'tcx LazyConst<'tcx>, user_ty: Option>>, }, InlineAsm { diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 13838e5d85dda..176c2f6564361 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -635,7 +635,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, }).collect() } ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => { - let len = len.unwrap_usize(cx.tcx); + let len = len.unwrap_evaluated().unwrap_usize(cx.tcx); if len != 0 && cx.is_uninhabited(sub_ty) { vec![] } else { @@ -1310,7 +1310,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, )]), PatternKind::Array { .. } => match pcx.ty.sty { ty::Array(_, length) => Some(vec![ - Slice(length.unwrap_usize(cx.tcx)) + Slice(length.unwrap_evaluated().unwrap_usize(cx.tcx)) ]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) }, @@ -1751,23 +1751,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (opt_ptr, n, ty) = match (value.val, &value.ty.sty) { - (ConstValue::ByRef(id, alloc, offset), ty::TyKind::Array(t, n)) => ( - Some(( - Pointer::new(id, offset), - alloc, - )), - n.unwrap_usize(cx.tcx), - t, - ), - (ConstValue::ScalarPair(ptr, n), ty::TyKind::Slice(t)) => ( - ptr.to_ptr().ok().map(|ptr| ( - ptr, - cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), - )), - n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, - t, - ), + let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { + ty::TyKind::Array(t, n) => + (value.to_ptr(), n.unwrap_evaluated().unwrap_usize(cx.tcx), t), + ty::TyKind::Slice(t) => { + match value.val { + ConstValue::ScalarPair(ptr, n) => ( + ptr.to_ptr().ok(), + n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, + t, + ), + _ => span_bug!( + pat.span, + "slice pattern constant must be scalar pair but is {:?}", + value, + ), + } + }, _ => span_bug!( pat.span, "unexpected const-val {:?} with ctor {:?}", diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 10d2d7bc1b18b..d7eeaf4365102 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Array(_, len) => { // fixed-length array - let len = len.unwrap_usize(self.tcx); + let len = len.unwrap_evaluated().unwrap_usize(self.tcx); assert!(len >= prefix.len() as u64 + suffix.len() as u64); PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix } } @@ -934,7 +934,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } ty::Array(_, n) => { PatternKind::Array { - prefix: (0..n.unwrap_usize(self.tcx)) + prefix: (0..n.unwrap_evaluated().unwrap_usize(self.tcx)) .map(|i| adt_subpattern(i as usize, None)) .collect(), slice: None, diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 190a381cf52a5..37c5340e0a26c 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -307,7 +307,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // u64 cast is from usize to u64, which is always good let val = Immediate::new_slice( ptr, - length.unwrap_usize(self.tcx.tcx), + length.unwrap_evaluated().unwrap_usize(self.tcx.tcx), self, ); self.write_immediate(val, dest) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 1ea3f78c2104f..04e0955ad6172 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; -use rustc::mir; +use rustc::{mir, ty}; use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx}; use rustc::mir::interpret::{ @@ -517,7 +517,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs()); self.layout_of(ty) })?; - let op = self.const_value_to_op(constant.literal.val)?; + let op = self.const_value_to_op(*constant.literal)?; OpTy { op, layout } } }; @@ -540,17 +540,20 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // `eval_operand`, ideally). pub(crate) fn const_value_to_op( &self, - val: ConstValue<'tcx>, + val: ty::LazyConst<'tcx>, ) -> EvalResult<'tcx, Operand> { trace!("const_value_to_op: {:?}", val); - match val { - ConstValue::Unevaluated(def_id, substs) => { + let val = match val { + ty::LazyConst::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; - Ok(*OpTy::from(self.const_eval_raw(GlobalId { + return Ok(*OpTy::from(self.const_eval_raw(GlobalId { instance, promoted: None, - })?)) - } + })?)); + }, + ty::LazyConst::Evaluated(c) => c, + }; + match val.val { ConstValue::ByRef(id, alloc, offset) => { // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen -- and for `static mut`, we copy on demand anyway. diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index d81a4d6a4bc84..757f94f2076ac 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -381,7 +381,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let param_env = ty::ParamEnv::reveal_all(); if let Ok(val) = tcx.const_eval(param_env.and(cid)) { - collect_const(tcx, val, instance.substs, &mut neighbors); + collect_const(tcx, val, &mut neighbors); } } MonoItem::Fn(instance) => { @@ -583,10 +583,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.super_rvalue(rvalue, location); } - fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { + fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); - collect_const(self.tcx, constant, self.param_substs, self.output); + collect_lazy_const(self.tcx, constant, self.param_substs, self.output); self.super_const(constant); } @@ -987,7 +987,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { let param_env = ty::ParamEnv::reveal_all(); if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) { - collect_const(self.tcx, val, instance.substs, &mut self.output); + collect_const(self.tcx, val, &mut self.output); } } hir::ItemKind::Fn(..) => { @@ -1198,7 +1198,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, promoted: Some(i), }; match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), + Ok(val) => collect_const(tcx, val, output), Err(ErrorHandled::Reported) => {}, Err(ErrorHandled::TooGeneric) => span_bug!( mir.promoted[i].span, "collection encountered polymorphic constant", @@ -1216,43 +1216,48 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output } +fn collect_lazy_const<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + constant: &ty::LazyConst<'tcx>, + param_substs: &'tcx Substs<'tcx>, + output: &mut Vec>, +) { + let (def_id, substs) = match *constant { + ty::LazyConst::Evaluated(c) => return collect_const(tcx, c, output), + ty::LazyConst::Unevaluated(did, substs) => (did, substs), + }; + let param_env = ty::ParamEnv::reveal_all(); + let substs = tcx.subst_and_normalize_erasing_regions( + param_substs, + param_env, + &substs, + ); + let instance = ty::Instance::resolve(tcx, + param_env, + def_id, + substs).unwrap(); + + let cid = GlobalId { + instance, + promoted: None, + }; + match tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(tcx, val, output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => span_bug!( + tcx.def_span(def_id), "collection encountered polymorphic constant", + ), + } +} + fn collect_const<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, constant: &ty::Const<'tcx>, - param_substs: &'tcx Substs<'tcx>, output: &mut Vec>, ) { debug!("visiting const {:?}", *constant); - let val = match constant.val { - ConstValue::Unevaluated(def_id, substs) => { - let param_env = ty::ParamEnv::reveal_all(); - let substs = tcx.subst_and_normalize_erasing_regions( - param_substs, - param_env, - &substs, - ); - let instance = ty::Instance::resolve(tcx, - param_env, - def_id, - substs).unwrap(); - - let cid = GlobalId { - instance, - promoted: None, - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => val.val, - Err(ErrorHandled::Reported) => return, - Err(ErrorHandled::TooGeneric) => span_bug!( - tcx.def_span(def_id), "collection encountered polymorphic constant", - ), - } - }, - _ => constant.val, - }; - match val { - ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"), + match constant.val { ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => { collect_miri(tcx, a.alloc_id, output); collect_miri(tcx, b.alloc_id, output); diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index e7f4451fdd7ee..8cd8eb3ad64c2 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -295,7 +295,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::Array(inner_type, len) => { output.push('['); self.push_type_name(inner_type, output); - write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap(); + write!(output, "; {}", len.unwrap_evaluated().unwrap_usize(self.tcx)).unwrap(); output.push(']'); }, ty::Slice(inner_type) => { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 2aa44cc181a56..c9c9afc3ef328 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -318,7 +318,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match self_ty.sty { _ if is_copy => builder.copy_shim(), ty::Array(ty, len) => { - let len = len.unwrap_usize(tcx); + let len = len.unwrap_evaluated().unwrap_usize(tcx); builder.array_shim(dest, src, ty, len) } ty::Closure(def_id, substs) => { @@ -459,7 +459,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: func_ty, user_ty: None, - literal: ty::Const::zero_sized(self.tcx, func_ty), + literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::zero_sized(self.tcx, func_ty), + )), }); let ref_loc = self.make_place( @@ -519,7 +521,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: self.tcx.types.usize, user_ty: None, - literal: ty::Const::from_usize(self.tcx, value), + literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::from_usize(self.tcx, value), + )), } } @@ -755,7 +759,9 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span, ty, user_ty: None, - literal: ty::Const::zero_sized(tcx, ty), + literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::zero_sized(tcx, ty) + )), }), vec![rcvr]) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 34f544745a787..a2a416e54d8ca 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -255,7 +255,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { source_info: SourceInfo, ) -> Option> { self.ecx.tcx.span = source_info.span; - match const_to_op(&self.ecx, c.literal) { + match const_to_op(&self.ecx, *c.literal, c.ty) { Ok(op) => { Some((op, c.span)) }, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index b98e3d7d8bb7a..06e16de8b43bc 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -533,7 +533,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { span, ty: self.tcx.types.bool, user_ty: None, - literal: ty::Const::from_bool(self.tcx, val), + literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::from_bool(self.tcx, val), + )), }))) } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 009570c378ad2..b464b7d65e466 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { *region = self.tcx.types.re_erased; } - fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { + fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) { *constant = self.tcx.erase_regions(constant); } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index b43e839271863..808c3aad29201 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -171,11 +171,11 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { span: source_info.span, ty: self.tcx.types.u32, user_ty: None, - literal: ty::Const::from_bits( + literal: self.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits( self.tcx, state_disc.into(), ty::ParamEnv::empty().and(self.tcx.types.u32) - ), + ))), }); Statement { source_info, @@ -717,7 +717,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: mir.span, ty: tcx.types.bool, user_ty: None, - literal: ty::Const::from_bool(tcx, false), + literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::from_bool(tcx, false), + )), }), expected: true, msg: message, diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7b04af62fe6cc..209c26a0c6c46 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -11,7 +11,6 @@ use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::mir::interpret::ConstValue; use rustc::traits::{self, TraitEngine}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; @@ -625,12 +624,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } Operand::Constant(ref constant) => { - if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { + if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal { // Don't peek inside trait associated constants. - if self.tcx.trait_of_item(def_id).is_some() { - self.add_type(constant.literal.ty); + if self.tcx.trait_of_item(*def_id).is_some() { + self.add_type(constant.ty); } else { - let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(def_id); + let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(*def_id); let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif"); self.add(qualif); @@ -638,7 +637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Just in case the type is more specific than // the definition, e.g., impl associated const // with type parameters, take it into account. - self.qualif.restrict(constant.literal.ty, self.tcx, self.param_env); + self.qualif.restrict(constant.ty, self.tcx, self.param_env); } } } @@ -713,7 +712,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `self.mode == Mode::Fn` condition // seems unnecessary, given that this is merely a ZST. - if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn { + let len = len.unwrap_evaluated().unwrap_usize(self.tcx); + if len == 0 && self.mode == Mode::Fn { forbidden_mut = false; } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 6cf9f43877b17..1d5bc4f9cc31b 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use rustc::ty::{TyCtxt, ParamEnv}; +use rustc::ty::{self, TyCtxt, ParamEnv}; use rustc::mir::*; use transform::{MirPass, MirSource}; @@ -30,23 +30,28 @@ impl MirPass for SimplifyBranches { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. } => { let switch_ty = ParamEnv::empty().and(switch_ty); - if let Some(constint) = c.literal.assert_bits(tcx, switch_ty) { - let (otherwise, targets) = targets.split_last().unwrap(); - let mut ret = TerminatorKind::Goto { target: *otherwise }; - for (&v, t) in values.iter().zip(targets.iter()) { - if v == constint { - ret = TerminatorKind::Goto { target: *t }; - break; + if let ty::LazyConst::Evaluated(c) = c.literal { + let c = c.assert_bits(tcx, switch_ty); + if let Some(constant) = c { + let (otherwise, targets) = targets.split_last().unwrap(); + let mut ret = TerminatorKind::Goto { target: *otherwise }; + for (&v, t) in values.iter().zip(targets.iter()) { + if v == constant { + ret = TerminatorKind::Goto { target: *t }; + break; + } } + ret + } else { + continue } - ret } else { continue } }, TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.assert_bool(tcx) == Some(true)) == expected => { + } if (c.literal.unwrap_evaluated().assert_bool(tcx) == Some(true)) == expected => { TerminatorKind::Goto { target } }, TerminatorKind::FalseEdges { real_target, .. } => { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 5ab9669baaca0..172993daa9a1c 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { } else { let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); if let ty::Array(item_ty, const_size) = place_ty.sty { - if let Some(size) = const_size.assert_usize(self.tcx) { + if let Some(size) = const_size.unwrap_evaluated().assert_usize(self.tcx) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported for array bigger then u32"); @@ -193,7 +193,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut { let opt_size = opt_src_place.and_then(|src_place| { let src_ty = src_place.ty(mir, tcx).to_ty(tcx); if let ty::Array(_, ref size_o) = src_ty.sty { - size_o.assert_usize(tcx) + size_o.unwrap_evaluated().assert_usize(tcx) } else { None } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 5a2f4be71cc2f..221c2d55eec97 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -809,7 +809,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } ty::Array(ety, size) => { - let size = size.assert_usize(self.tcx()); + let size = size.unwrap_evaluated().assert_usize(self.tcx()); self.open_drop_for_array(ety, size) }, ty::Slice(ety) => self.open_drop_for_array(ety, None), @@ -963,7 +963,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> span: self.source_info.span, ty: self.tcx().types.usize, user_ty: None, - literal: ty::Const::from_usize(self.tcx(), val.into()), + literal: self.tcx().intern_lazy_const(ty::LazyConst::Evaluated( + ty::Const::from_usize(self.tcx(), val.into()) + )), }) } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6353eab6f6553..fca208b340d2a 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -399,12 +399,21 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> { self.push(&format!("+ literal: {:?}", literal)); } - fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { + fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, _: Location) { self.super_const(constant); - let ty::Const { ty, val, .. } = constant; - self.push("ty::Const"); - self.push(&format!("+ ty: {:?}", ty)); - self.push(&format!("+ val: {:?}", val)); + match constant { + ty::LazyConst::Evaluated(constant) => { + let ty::Const { ty, val, .. } = constant; + self.push("ty::Const"); + self.push(&format!("+ ty: {:?}", ty)); + self.push(&format!("+ val: {:?}", val)); + }, + ty::LazyConst::Unevaluated(did, substs) => { + self.push("ty::LazyConst::Unevaluated"); + self.push(&format!("+ did: {:?}", did)); + self.push(&format!("+ substs: {:?}", substs)); + }, + } } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 98a2f4bf0a15b..71f4945fd648d 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -239,7 +239,7 @@ fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> { fn wf_clause_for_array<'tcx>( tcx: ty::TyCtxt<'_, '_, 'tcx>, - length: &'tcx ty::Const<'tcx> + length: &'tcx ty::LazyConst<'tcx> ) -> Clauses<'tcx> { let ty = generic_types::bound(tcx, 0); let array_ty = tcx.mk_ty(ty::Array(ty, length)); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1db7141917f98..e018aa3b26d91 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1772,7 +1772,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); let substs = Substs::identity_for_item(tcx, length_def_id); - let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize); + let length = ty::LazyConst::Unevaluated(length_def_id, substs); + let length = tcx.intern_lazy_const(length); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index b66c383edb51e..13311a2efd5a3 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -377,7 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expected_ty = self.structurally_resolved_type(pat.span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { ty::Array(inner_ty, size) => { - let size = size.unwrap_usize(tcx); + let size = size.unwrap_evaluated().unwrap_usize(tcx); let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { if min_len != size { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8262c30679693..bcdf7eb00df6f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3483,7 +3483,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ty::Array(_, len) => { if let (Some(len), Ok(user_index)) = ( - len.assert_usize(self.tcx), + len.unwrap_evaluated().assert_usize(self.tcx), field.as_str().parse::() ) { let base = self.tcx.sess.source_map() @@ -4472,7 +4472,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if element_ty.references_error() { tcx.types.err } else if let Ok(count) = count { - tcx.mk_ty(ty::Array(t, count)) + tcx.mk_ty(ty::Array(t, tcx.intern_lazy_const(ty::LazyConst::Evaluated(count)))) } else { tcx.types.err } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 38b2452b420e9..3aa752b35adcf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -13,7 +13,6 @@ use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; -use rustc::mir::interpret::ConstValue; use rustc::middle::resolve_lifetime as rl; use rustc::middle::lang_items; use rustc::middle::stability; @@ -2420,10 +2419,10 @@ impl Clean for hir::Ty { instance: ty::Instance::new(def_id, substs), promoted: None }; - let length = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| { - ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize) - }); - let length = print_const(cx, length); + let length = match cx.tcx.const_eval(param_env.and(cid)) { + Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)), + Err(_) => "_".to_string(), + }; Array(box ty.clean(cx), length) }, TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), @@ -2583,15 +2582,15 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Str => Primitive(PrimitiveType::Str), ty::Slice(ty) => Slice(box ty.clean(cx)), ty::Array(ty, n) => { - let mut n = cx.tcx.lift(&n).expect("array lift failed"); - if let ConstValue::Unevaluated(def_id, substs) = n.val { + let mut n = *cx.tcx.lift(&n).expect("array lift failed"); + if let ty::LazyConst::Unevaluated(def_id, substs) = n { let param_env = cx.tcx.param_env(def_id); let cid = GlobalId { instance: ty::Instance::new(def_id, substs), promoted: None }; if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) { - n = new_n; + n = ty::LazyConst::Evaluated(new_n); } }; let n = print_const(cx, n); @@ -3691,16 +3690,16 @@ fn name_from_pat(p: &hir::Pat) -> String { } } -fn print_const(cx: &DocContext, n: &ty::Const) -> String { - match n.val { - ConstValue::Unevaluated(def_id, _) => { +fn print_const(cx: &DocContext, n: ty::LazyConst) -> String { + match n { + ty::LazyConst::Unevaluated(def_id, _) => { if let Some(node_id) = cx.tcx.hir().as_local_node_id(def_id) { print_const_expr(cx, cx.tcx.hir().body_owned_by(node_id)) } else { inline::print_inlined_const(cx, def_id) } }, - _ => { + ty::LazyConst::Evaluated(n) => { let mut s = String::new(); ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed"); // array lengths are obviously usize From ba90f161ae211d035edaa027af67451daa3d8774 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 12 Dec 2018 09:13:57 +0100 Subject: [PATCH 13/28] Mingw is special wrt type sizes --- src/librustc/ty/sty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6a9a9fd0ed17c..aed76fb99f790 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2028,7 +2028,7 @@ pub enum LazyConst<'tcx> { Evaluated(&'tcx Const<'tcx>), } -static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::>() == 24); +static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::>() <= 24); impl<'tcx> LazyConst<'tcx> { pub fn unwrap_evaluated(self) -> &'tcx Const<'tcx> { From 8e7a06adcc12715b48237ce641939c43182dc0e4 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 12 Dec 2018 17:19:11 +0100 Subject: [PATCH 14/28] Simplify and fix some diagnostics around arrays --- src/librustc/traits/error_reporting.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index df4b7c7731bb0..c0f50ecd28824 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -418,20 +418,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(format!("[{}]", self.tcx.type_of(def.did).to_string())), )); let tcx = self.tcx; - if let ty::LazyConst::Evaluated(len) = len { - if let Some(len) = len.val.try_to_scalar().and_then(|scalar| { - scalar.to_usize(&tcx).ok() - }) { - flags.push(( - "_Self".to_owned(), - Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), - )); - } else { - flags.push(( - "_Self".to_owned(), - Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())), - )); - } + if let Some(len) = len.assert_usize(tcx) { + flags.push(( + "_Self".to_owned(), + Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), + )); + } else { + flags.push(( + "_Self".to_owned(), + Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())), + )); } } } From 8449dda425005b18310f7d6f9a8c8c74620331f3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 09:34:23 +0100 Subject: [PATCH 15/28] Add `unwrap_usize` to `LazyConst`, too --- src/librustc/mir/tcx.rs | 2 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/sty.rs | 14 ++++++-------- src/librustc_codegen_llvm/debuginfo/metadata.rs | 2 +- src/librustc_codegen_llvm/debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/borrow_check/places_conflict.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 6 +++--- src/librustc_mir/hair/pattern/mod.rs | 4 ++-- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/monomorphize/item.rs | 2 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/simplify_branches.rs | 5 ++--- .../transform/uniform_array_move_out.rs | 4 ++-- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- 21 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 6dda1933bbafa..c5b884525da4b 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { PlaceTy::Ty { ty: match ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_evaluated().unwrap_usize(tcx); + let size = size.unwrap_usize(tcx); let len = size - (from as u64) - (to as u64); tcx.mk_array(inner, len) } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 1f25925a8e1d1..171c53b7b20ba 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -543,7 +543,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } let element = self.layout_of(element)?; - let count = count.unwrap_evaluated().unwrap_usize(tcx); + let count = count.unwrap_usize(tcx); let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index aed76fb99f790..6764a1545cc52 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2031,13 +2031,6 @@ pub enum LazyConst<'tcx> { static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::>() <= 24); impl<'tcx> LazyConst<'tcx> { - pub fn unwrap_evaluated(self) -> &'tcx Const<'tcx> { - match self { - LazyConst::Evaluated(c) => c, - LazyConst::Unevaluated(..) => bug!("unexpected unevaluated constant"), - } - } - pub fn map_evaluated(self, f: impl FnOnce(&'tcx Const<'tcx>) -> Option) -> Option { match self { LazyConst::Evaluated(c) => f(c), @@ -2045,9 +2038,14 @@ impl<'tcx> LazyConst<'tcx> { } } - pub fn assert_usize(self, tcx: TyCtxt<'_, '_, 'tcx>) -> Option { + pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option { self.map_evaluated(|c| c.assert_usize(tcx)) } + + #[inline] + pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 { + self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize") + } } /// Typed constant value. diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index bec0cfa0d862f..0fd04e9d20393 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -302,7 +302,7 @@ fn fixed_vec_metadata( let upper_bound = match array_or_slice_type.sty { ty::Array(_, len) => { - len.unwrap_evaluated().unwrap_usize(cx.tcx) as c_longlong + len.unwrap_usize(cx.tcx) as c_longlong } _ => -1 }; diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index c1309569c7955..c8cbd735e850d 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -88,7 +88,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); - output.push_str(&format!("; {}", len.unwrap_evaluated().unwrap_usize(cx.tcx))); + output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx))); output.push(']'); }, ty::Slice(inner_type) => { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 166655f6a8061..b88ec075653ba 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -171,7 +171,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( let (source, target) = cx.tcx().struct_lockstep_tails(source, target); match (&source.sty, &target.sty) { (&ty::Array(_, len), &ty::Slice(_)) => { - cx.const_usize(len.unwrap_evaluated().unwrap_usize(cx.tcx())) + cx.const_usize(len.unwrap_usize(cx.tcx())) } (&ty::Dynamic(..), &ty::Dynamic(..)) => { // For now, upcasts are limited to changes in marker diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 58325e3443266..35bd3a32e8182 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .and_then(|c| { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { - ty::Array(_, n) => n.unwrap_evaluated().unwrap_usize(bx.tcx()), + ty::Array(_, n) => n.unwrap_usize(bx.tcx()), ref other => bug!("invalid simd shuffle type: {}", other), }; let values: Result, ErrorHandled> = (0..fields).map(|field| { diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 404ee86c6a117..9ca5414fa717e 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -537,7 +537,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let mir::Place::Local(index) = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.sty { - let n = n.unwrap_evaluated().unwrap_usize(bx.cx().tcx()); + let n = n.unwrap_usize(bx.cx().tcx()); return bx.cx().const_usize(n); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 3b49b8a74f769..180aa1907e8d1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -572,7 +572,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ProjectionElem::Subslice { from, to } => PlaceTy::Ty { ty: match base_ty.sty { ty::Array(inner, size) => { - let size = size.unwrap_evaluated().unwrap_usize(tcx); + let size = size.unwrap_usize(tcx); let min_size = (from as u64) + (to as u64); if let Some(rest_size) = size.checked_sub(min_size) { tcx.mk_array(inner, rest_size) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 88c27a869c089..ac7182abb36da 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -388,7 +388,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>( (Place::Promoted(p1), Place::Promoted(p2)) => { if p1.0 == p2.0 { if let ty::Array(_, size) = p1.1.sty { - if size.unwrap_evaluated().unwrap_usize(tcx) == 0 { + if size.unwrap_usize(tcx) == 0 { // Ignore conflicts with promoted [T; 0]. debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); return Overlap::Disjoint; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 176c2f6564361..0f5510a2921d7 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -635,7 +635,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, }).collect() } ty::Array(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => { - let len = len.unwrap_evaluated().unwrap_usize(cx.tcx); + let len = len.unwrap_usize(cx.tcx); if len != 0 && cx.is_uninhabited(sub_ty) { vec![] } else { @@ -1310,7 +1310,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, )]), PatternKind::Array { .. } => match pcx.ty.sty { ty::Array(_, length) => Some(vec![ - Slice(length.unwrap_evaluated().unwrap_usize(cx.tcx)) + Slice(length.unwrap_usize(cx.tcx)) ]), _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty) }, @@ -1753,7 +1753,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // slices let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { ty::TyKind::Array(t, n) => - (value.to_ptr(), n.unwrap_evaluated().unwrap_usize(cx.tcx), t), + (value.to_ptr(), n.unwrap_usize(cx.tcx), t), ty::TyKind::Slice(t) => { match value.val { ConstValue::ScalarPair(ptr, n) => ( diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index d7eeaf4365102..10d2d7bc1b18b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Array(_, len) => { // fixed-length array - let len = len.unwrap_evaluated().unwrap_usize(self.tcx); + let len = len.unwrap_usize(self.tcx); assert!(len >= prefix.len() as u64 + suffix.len() as u64); PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix } } @@ -934,7 +934,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } ty::Array(_, n) => { PatternKind::Array { - prefix: (0..n.unwrap_evaluated().unwrap_usize(self.tcx)) + prefix: (0..n.unwrap_usize(self.tcx)) .map(|i| adt_subpattern(i as usize, None)) .collect(), slice: None, diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 37c5340e0a26c..190a381cf52a5 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -307,7 +307,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // u64 cast is from usize to u64, which is always good let val = Immediate::new_slice( ptr, - length.unwrap_evaluated().unwrap_usize(self.tcx.tcx), + length.unwrap_usize(self.tcx.tcx), self, ); self.write_immediate(val, dest) diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 8cd8eb3ad64c2..e7f4451fdd7ee 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -295,7 +295,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::Array(inner_type, len) => { output.push('['); self.push_type_name(inner_type, output); - write!(output, "; {}", len.unwrap_evaluated().unwrap_usize(self.tcx)).unwrap(); + write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap(); output.push(']'); }, ty::Slice(inner_type) => { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index c9c9afc3ef328..7bf02ab6c1a80 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -318,7 +318,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match self_ty.sty { _ if is_copy => builder.copy_shim(), ty::Array(ty, len) => { - let len = len.unwrap_evaluated().unwrap_usize(tcx); + let len = len.unwrap_usize(tcx); builder.array_shim(dest, src, ty, len) } ty::Closure(def_id, substs) => { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 209c26a0c6c46..f35685b7b0c9d 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -712,7 +712,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `self.mode == Mode::Fn` condition // seems unnecessary, given that this is merely a ZST. - let len = len.unwrap_evaluated().unwrap_usize(self.tcx); + let len = len.unwrap_usize(self.tcx); if len == 0 && self.mode == Mode::Fn { forbidden_mut = false; } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 1d5bc4f9cc31b..60a569e297d29 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -51,9 +51,8 @@ impl MirPass for SimplifyBranches { }, TerminatorKind::Assert { target, cond: Operand::Constant(ref c), expected, .. - } if (c.literal.unwrap_evaluated().assert_bool(tcx) == Some(true)) == expected => { - TerminatorKind::Goto { target } - }, + } if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected => + TerminatorKind::Goto { target }, TerminatorKind::FalseEdges { real_target, .. } => { TerminatorKind::Goto { target: real_target } }, diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 172993daa9a1c..5ab9669baaca0 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { } else { let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); if let ty::Array(item_ty, const_size) = place_ty.sty { - if let Some(size) = const_size.unwrap_evaluated().assert_usize(self.tcx) { + if let Some(size) = const_size.assert_usize(self.tcx) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported for array bigger then u32"); @@ -193,7 +193,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut { let opt_size = opt_src_place.and_then(|src_place| { let src_ty = src_place.ty(mir, tcx).to_ty(tcx); if let ty::Array(_, ref size_o) = src_ty.sty { - size_o.unwrap_evaluated().assert_usize(tcx) + size_o.assert_usize(tcx) } else { None } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 221c2d55eec97..8b55a4424ae29 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -809,7 +809,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.complete_drop(Some(DropFlagMode::Deep), succ, unwind) } ty::Array(ety, size) => { - let size = size.unwrap_evaluated().assert_usize(self.tcx()); + let size = size.assert_usize(self.tcx()); self.open_drop_for_array(ety, size) }, ty::Slice(ety) => self.open_drop_for_array(ety, None), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 13311a2efd5a3..b66c383edb51e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -377,7 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expected_ty = self.structurally_resolved_type(pat.span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { ty::Array(inner_ty, size) => { - let size = size.unwrap_evaluated().unwrap_usize(tcx); + let size = size.unwrap_usize(tcx); let min_len = before.len() as u64 + after.len() as u64; if slice.is_none() { if min_len != size { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bcdf7eb00df6f..b2ea170697737 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3483,7 +3483,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ty::Array(_, len) => { if let (Some(len), Ok(user_index)) = ( - len.unwrap_evaluated().assert_usize(self.tcx), + len.assert_usize(self.tcx), field.as_str().parse::() ) { let base = self.tcx.sess.source_map() From 77bf3d0cf81fd5e3e4d0fe4e397f7959dcd23cca Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 10:04:28 +0100 Subject: [PATCH 16/28] `const_to_op` is now `lazy_const_to_op` --- src/librustc_mir/const_eval.rs | 6 +++--- src/librustc_mir/transform/const_prop.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 58a0f13733ea8..2722355b050f9 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -137,7 +137,7 @@ pub fn op_to_const<'tcx>( Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) } -pub fn const_to_op<'tcx>( +pub fn lazy_const_to_op<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, cnst: ty::LazyConst<'tcx>, ty: ty::Ty<'tcx>, @@ -516,7 +516,7 @@ pub fn const_field<'a, 'tcx>( let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let result = (|| { // get the operand again - let op = const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?; + let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(value), value.ty)?; // downcast let down = match variant { None => op, @@ -543,7 +543,7 @@ pub fn const_variant_index<'a, 'tcx>( ) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}, {:?}", instance, val); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); - let op = const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?; + let op = lazy_const_to_op(&ecx, ty::LazyConst::Evaluated(val), val.ty)?; Ok(ecx.read_discriminant(op)?.1) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a2a416e54d8ca..2e72f80425d62 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -20,7 +20,7 @@ use rustc::ty::layout::{ use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind}; use const_eval::{ - CompileTimeInterpreter, const_to_op, error_to_const_error, eval_promoted, mk_borrowck_eval_cx + CompileTimeInterpreter, lazy_const_to_op, error_to_const_error, eval_promoted, mk_borrowck_eval_cx }; use transform::{MirPass, MirSource}; @@ -255,7 +255,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { source_info: SourceInfo, ) -> Option> { self.ecx.tcx.span = source_info.span; - match const_to_op(&self.ecx, *c.literal, c.ty) { + match lazy_const_to_op(&self.ecx, *c.literal, c.ty) { Ok(op) => { Some((op, c.span)) }, From 296a8cd0fa00d9a413bbb66ed496f3be453e17ac Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 11:11:12 +0100 Subject: [PATCH 17/28] `<&'tcx ty::Const as Deref>::deref` --- src/librustc/mir/interpret/error.rs | 2 +- src/librustc/mir/mod.rs | 8 ++--- src/librustc/ty/codec.rs | 16 --------- src/librustc/ty/context.rs | 27 ++------------- src/librustc/ty/query/keys.rs | 2 +- src/librustc/ty/structural_impls.rs | 37 +++++++++++++++++--- src/librustc/ty/sty.rs | 39 ++++++++-------------- src/librustc_codegen_ssa/mir/constant.rs | 6 ++-- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 4 +-- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/misc.rs | 2 +- src/librustc_mir/const_eval.rs | 8 ++--- src/librustc_mir/hair/constant.rs | 4 +-- src/librustc_mir/hair/cx/expr.rs | 3 +- src/librustc_mir/hair/cx/mod.rs | 6 ++-- src/librustc_mir/hair/pattern/_match.rs | 4 +-- src/librustc_mir/hair/pattern/mod.rs | 14 ++++---- src/librustc_mir/monomorphize/collector.rs | 4 +-- src/librustc_mir/shim.rs | 4 +-- 20 files changed, 86 insertions(+), 108 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 19be0c08ef13b..c3fe5d773ab16 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -37,7 +37,7 @@ impl ErrorHandled { } pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; -pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; +pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct ConstEvalErr<'tcx> { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index eafae6d9c9e8d..a1a6e890b1292 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1666,7 +1666,7 @@ impl<'tcx> TerminatorKind<'tcx> { ), ty: switch_ty, }; - fmt_const_val(&mut s, &c).unwrap(); + fmt_const_val(&mut s, c).unwrap(); s.into() }).chain(iter::once("otherwise".into())) .collect() @@ -2155,7 +2155,7 @@ impl<'tcx> Operand<'tcx> { ty, user_ty: None, literal: tcx.intern_lazy_const( - ty::LazyConst::Evaluated(ty::Const::zero_sized(tcx, ty)), + ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)), ), }) } @@ -2663,14 +2663,14 @@ impl<'tcx> Debug for Constant<'tcx> { /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output. pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result { - match const_val { + match *const_val { ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val), ty::LazyConst::Evaluated(c) => fmt_const_val(f, c), } } /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output. -pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const<'_>) -> fmt::Result { +pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result { use ty::TyKind::*; let value = const_val.val; let ty = const_val.ty; diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 57b99db0c7d54..e0e4d9c362a6c 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -246,15 +246,6 @@ pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D) .intern_canonical_var_infos(interned?.as_slice())) } -#[inline] -pub fn decode_const<'a, 'tcx, D>(decoder: &mut D) - -> Result<&'tcx ty::Const<'tcx>, D::Error> - where D: TyDecoder<'a, 'tcx>, - 'tcx: 'a, -{ - Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?)) -} - #[inline] pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx ty::LazyConst<'tcx>, D::Error> @@ -398,13 +389,6 @@ macro_rules! implement_ty_decoder { } } - impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>> - for $DecoderName<$($typaram),*> { - fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { - decode_const(self) - } - } - impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 715e7367fada7..108fcc1bd3f21 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -122,7 +122,6 @@ pub struct CtxtInterners<'tcx> { region: InternedSet<'tcx, RegionKind>, existential_predicates: InternedSet<'tcx, List>>, predicates: InternedSet<'tcx, List>>, - const_: InternedSet<'tcx, Const<'tcx>>, clauses: InternedSet<'tcx, List>>, goal: InternedSet<'tcx, GoalKind<'tcx>>, goal_list: InternedSet<'tcx, List>>, @@ -140,7 +139,6 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { existential_predicates: Default::default(), canonical_var_infos: Default::default(), predicates: Default::default(), - const_: Default::default(), clauses: Default::default(), goal: Default::default(), goal_list: Default::default(), @@ -1071,24 +1069,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn alloc_const_slice(self, values: &[&'tcx ty::Const<'tcx>]) - -> &'tcx [&'tcx ty::Const<'tcx>] { - if values.is_empty() { - &[] - } else { - self.interners.arena.alloc_slice(values) - } - } - - pub fn alloc_name_const_slice(self, values: &[(ast::Name, &'tcx ty::Const<'tcx>)]) - -> &'tcx [(ast::Name, &'tcx ty::Const<'tcx>)] { - if values.is_empty() { - &[] - } else { - self.interners.arena.alloc_slice(values) - } - } - pub fn intern_const_alloc( self, alloc: Allocation, @@ -1833,9 +1813,9 @@ impl<'a, 'tcx> Lift<'tcx> for &'a LazyConst<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Const<'a> { - type Lifted = &'tcx Const<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Const<'tcx>> { +impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { + type Lifted = &'tcx mir::interpret::Allocation; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } @@ -2516,7 +2496,6 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { direct_interners!('tcx, region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind, - const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>, goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx> ); diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 959a5ff5767a3..af6f5a00dee5c 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -136,7 +136,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx>{ } } -impl<'tcx> Key for &'tcx ty::Const<'tcx> { +impl<'tcx> Key for ty::Const<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index b4af81ab69d8b..258470bf6f860 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -53,7 +53,6 @@ CloneTypeFoldableAndLiftImpls! { ::ty::UniverseIndex, ::ty::Variance, ::syntax_pos::Span, - ConstValue<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -487,6 +486,26 @@ BraceStructLiftImpl! { } } +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> { + type Lifted = ty::Const<'tcx>; + val, ty + } +} + +impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> { + type Lifted = ConstValue<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + match *self { + ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)), + ConstValue::ScalarPair(x, y) => Some(ConstValue::ScalarPair(x, y)), + ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef( + x, alloc.lift_to_tcx(tcx)?, z, + )), + } + } +} + /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. // @@ -1042,17 +1061,27 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let ty = self.ty.fold_with(folder); let val = self.val.fold_with(folder); - folder.tcx().mk_const(ty::Const { + ty::Const { ty, val - }) + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { self.ty.visit_with(visitor) || self.val.visit_with(visitor) } } + +impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _visitor: &mut V) -> bool { + false + } +} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6764a1545cc52..ebaf6a73e34d4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2025,13 +2025,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// code is monomorphic enough for that. pub enum LazyConst<'tcx> { Unevaluated(DefId, &'tcx Substs<'tcx>), - Evaluated(&'tcx Const<'tcx>), + Evaluated(Const<'tcx>), } -static_assert!(MEM_SIZE_OF_LAZY_CONST: ::std::mem::size_of::>() <= 24); - impl<'tcx> LazyConst<'tcx> { - pub fn map_evaluated(self, f: impl FnOnce(&'tcx Const<'tcx>) -> Option) -> Option { + pub fn map_evaluated(self, f: impl FnOnce(Const<'tcx>) -> Option) -> Option { match self { LazyConst::Evaluated(c) => f(c), LazyConst::Unevaluated(..) => None, @@ -2057,25 +2055,15 @@ pub struct Const<'tcx> { } impl<'tcx> Const<'tcx> { - #[inline] - pub fn from_const_value( - tcx: TyCtxt<'_, '_, 'tcx>, - val: ConstValue<'tcx>, - ty: Ty<'tcx>, - ) -> &'tcx Self { - tcx.mk_const(Const { - val, - ty, - }) - } - #[inline] pub fn from_scalar( - tcx: TyCtxt<'_, '_, 'tcx>, val: Scalar, ty: Ty<'tcx>, - ) -> &'tcx Self { - Self::from_const_value(tcx, ConstValue::Scalar(val), ty) + ) -> Self { + Self { + val: ConstValue::Scalar(val), + ty, + } } #[inline] @@ -2083,7 +2071,7 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'_, '_, 'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> &'tcx Self { + ) -> Self { let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).unwrap_or_else(|e| { panic!("could not compute layout for {:?}: {:?}", ty, e) @@ -2091,21 +2079,21 @@ impl<'tcx> Const<'tcx> { let shift = 128 - size.bits(); let truncated = (bits << shift) >> shift; assert_eq!(truncated, bits, "from_bits called with untruncated value"); - Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) + Self::from_scalar(Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) } #[inline] - pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self { - Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty) + pub fn zero_sized(ty: Ty<'tcx>) -> Self { + Self::from_scalar(Scalar::Bits { bits: 0, size: 0 }, ty) } #[inline] - pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self { + pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] - pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self { + pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } @@ -2171,5 +2159,4 @@ impl<'tcx> Const<'tcx> { } } -impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {} diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 35bd3a32e8182..e6d6ef1d7a38b 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -15,7 +15,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &Bx, constant: &'tcx ty::LazyConst<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { + ) -> Result, ErrorHandled> { match *constant { ty::LazyConst::Unevaluated(def_id, ref substs) => { let tcx = bx.tcx(); @@ -35,7 +35,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &Bx, constant: &mir::Constant<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { + ) -> Result, ErrorHandled> { let c = self.monomorphize(&constant.literal); self.fully_evaluate(bx, c) } @@ -46,7 +46,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &Bx, span: Span, ty: Ty<'tcx>, - constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>, + constant: Result, ErrorHandled>, ) -> (Bx::Value, Ty<'tcx>) { constant .and_then(|c| { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index bb55bf3b46cd4..2026e042ef0eb 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: &'tcx ty::Const<'tcx> + val: ty::Const<'tcx> ) -> Result { let layout = bx.cx().layout_of(val.ty); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index fe5bc6e19db65..409b6c038ab69 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -658,12 +658,12 @@ enum TestKind<'tcx> { SwitchInt { switch_ty: Ty<'tcx>, options: Vec, - indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>, + indices: FxHashMap, usize>, }, // test for equality Eq { - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ty: Ty<'tcx>, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f601e38717f2d..3d960a2dd288a 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidate: &Candidate<'pat, 'tcx>, switch_ty: Ty<'tcx>, options: &mut Vec, - indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>) + indices: &mut FxHashMap, usize>) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 9745fe392b652..c849c02242840 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -27,7 +27,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn literal_operand(&mut self, span: Span, ty: Ty<'tcx>, - literal: &'tcx ty::Const<'tcx>) + literal: ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 2722355b050f9..01177e5e49a0e 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -95,7 +95,7 @@ pub fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, op: OpTy<'tcx>, may_normalize: bool, -) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { +) -> EvalResult<'tcx, ty::Const<'tcx>> { // We do not normalize just any data. Only scalar layout and fat pointers. let normalize = may_normalize && match op.layout.abi { @@ -134,7 +134,7 @@ pub fn op_to_const<'tcx>( Ok(Immediate::ScalarPair(a, b)) => ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?), }; - Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) + Ok(ty::Const { val, ty: op.layout.ty }) } pub fn lazy_const_to_op<'tcx>( @@ -510,7 +510,7 @@ pub fn const_field<'a, 'tcx>( instance: ty::Instance<'tcx>, variant: Option, field: mir::Field, - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { trace!("const_field: {:?}, {:?}, {:?}", instance, field, value); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); @@ -539,7 +539,7 @@ pub fn const_variant_index<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, - val: &'tcx ty::Const<'tcx>, + val: ty::Const<'tcx>, ) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}, {:?}", instance, val); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index c98ef31c2bae2..37d741d2606d5 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -14,7 +14,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, neg: bool, -) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { +) -> Result, LitToConstError> { use syntax::ast::*; let trunc = |n| { @@ -64,7 +64,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), }; - Ok(ty::Const::from_const_value(tcx, lit, ty)) + Ok(ty::Const { val: lit, ty }) } fn parse_float<'tcx>( diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index e2d0f6b0ae625..532e6783f2f2b 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -871,7 +871,7 @@ fn method_callee<'a, 'gcx, 'tcx>( span, kind: ExprKind::Literal { literal: cx.tcx().intern_lazy_const(ty::LazyConst::Evaluated( - ty::Const::zero_sized(cx.tcx(), ty) + ty::Const::zero_sized(ty) )), user_ty, }, @@ -933,7 +933,6 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { literal: cx.tcx.intern_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized( - cx.tcx, cx.tables().node_id_to_type(expr.hir_id), ))), user_ty, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 96ea668dd8f03..6113d88e09591 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -134,7 +134,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, sp: Span, neg: bool, - ) -> &'tcx ty::Const<'tcx> { + ) -> ty::Const<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); match lit_to_const(lit, self.tcx, ty, neg) { @@ -169,14 +169,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { method_name: &str, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { + -> (Ty<'tcx>, ty::Const<'tcx>) { let method_name = Symbol::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); + return (method_ty, ty::Const::zero_sized(method_ty)); } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 0f5510a2921d7..57b0fb1d8be1e 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -420,7 +420,7 @@ pub enum Constructor<'tcx> { /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(&'tcx ty::Const<'tcx>), + ConstantValue(ty::Const<'tcx>), /// Ranges of literal values (`2...5` and `2..5`). ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), /// Array patterns of length n. @@ -1787,7 +1787,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( &cx.tcx, ptr, layout.size, ).ok()?; let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let value = ty::Const::from_scalar(scalar, ty); let pattern = Pattern { ty, span: pat.span, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 10d2d7bc1b18b..f52aeded19ae7 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -123,7 +123,7 @@ pub enum PatternKind<'tcx> { }, Constant { - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, }, Range(PatternRange<'tcx>), @@ -147,8 +147,8 @@ pub enum PatternKind<'tcx> { #[derive(Clone, Copy, Debug, PartialEq)] pub struct PatternRange<'tcx> { - pub lo: &'tcx ty::Const<'tcx>, - pub hi: &'tcx ty::Const<'tcx>, + pub lo: ty::Const<'tcx>, + pub hi: ty::Const<'tcx>, pub ty: Ty<'tcx>, pub end: RangeEnd, } @@ -857,7 +857,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn const_to_pat( &self, instance: ty::Instance<'tcx>, - cv: &'tcx ty::Const<'tcx>, + cv: ty::Const<'tcx>, id: hir::HirId, span: Span, ) -> Pattern<'tcx> { @@ -1018,7 +1018,7 @@ macro_rules! CloneImpls { } CloneImpls!{ <'tcx> - Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>, + Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>, Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>, UserTypeProjection<'tcx>, PatternTypeProjection<'tcx> @@ -1140,8 +1140,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { pub fn compare_const_vals<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 757f94f2076ac..eabfd47c9fb90 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1252,10 +1252,10 @@ fn collect_lazy_const<'a, 'tcx>( fn collect_const<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - constant: &ty::Const<'tcx>, + constant: ty::Const<'tcx>, output: &mut Vec>, ) { - debug!("visiting const {:?}", *constant); + debug!("visiting const {:?}", constant); match constant.val { ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 7bf02ab6c1a80..751815eab287b 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { ty: func_ty, user_ty: None, literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( - ty::Const::zero_sized(self.tcx, func_ty), + ty::Const::zero_sized(func_ty), )), }); @@ -760,7 +760,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty, user_ty: None, literal: tcx.intern_lazy_const(ty::LazyConst::Evaluated( - ty::Const::zero_sized(tcx, ty) + ty::Const::zero_sized(ty) )), }), vec![rcvr]) From 8d7f6a78e00695dc86109f49342deb474a0adb48 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 11:15:18 +0100 Subject: [PATCH 18/28] Simplify bit inspection of a constant --- .../transform/simplify_branches.rs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 60a569e297d29..abaea70946383 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use rustc::ty::{self, TyCtxt, ParamEnv}; +use rustc::ty::{TyCtxt, ParamEnv}; use rustc::mir::*; use transform::{MirPass, MirSource}; @@ -30,21 +30,17 @@ impl MirPass for SimplifyBranches { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. } => { let switch_ty = ParamEnv::empty().and(switch_ty); - if let ty::LazyConst::Evaluated(c) = c.literal { - let c = c.assert_bits(tcx, switch_ty); - if let Some(constant) = c { - let (otherwise, targets) = targets.split_last().unwrap(); - let mut ret = TerminatorKind::Goto { target: *otherwise }; - for (&v, t) in values.iter().zip(targets.iter()) { - if v == constant { - ret = TerminatorKind::Goto { target: *t }; - break; - } + let constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty)); + if let Some(constant) = constant { + let (otherwise, targets) = targets.split_last().unwrap(); + let mut ret = TerminatorKind::Goto { target: *otherwise }; + for (&v, t) in values.iter().zip(targets.iter()) { + if v == constant { + ret = TerminatorKind::Goto { target: *t }; + break; } - ret - } else { - continue } + ret } else { continue } From f7e04873fa3397ba63dcce43ce44a0bb196435ea Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 11:19:34 +0100 Subject: [PATCH 19/28] Undo a few - now unnecessary - changes --- src/librustc_mir/hair/pattern/_match.rs | 3 +-- src/librustc_mir/transform/qualify_consts.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 57b0fb1d8be1e..dc7331a2cd92d 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1752,8 +1752,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // they should be pointing to memory is when they are subslices of nonzero // slices let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { - ty::TyKind::Array(t, n) => - (value.to_ptr(), n.unwrap_usize(cx.tcx), t), + ty::TyKind::Array(t, n) => (value.to_ptr(), n.unwrap_usize(cx.tcx), t), ty::TyKind::Slice(t) => { match value.val { ConstValue::ScalarPair(ptr, n) => ( diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index f35685b7b0c9d..a04dd5bb5970f 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -712,8 +712,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `self.mode == Mode::Fn` condition // seems unnecessary, given that this is merely a ZST. - let len = len.unwrap_usize(self.tcx); - if len == 0 && self.mode == Mode::Fn { + if len.unwrap_usize(self.tcx) == 0 && self.mode == Mode::Fn { forbidden_mut = false; } } From 0c4db3fe8dcfc936140e4b0037b160a63075c94b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 12:20:29 +0100 Subject: [PATCH 20/28] Pacify tidy --- src/librustc_mir/transform/const_prop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 2e72f80425d62..03d6d3868c9f0 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -20,7 +20,8 @@ use rustc::ty::layout::{ use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind}; use const_eval::{ - CompileTimeInterpreter, lazy_const_to_op, error_to_const_error, eval_promoted, mk_borrowck_eval_cx + CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx, + lazy_const_to_op, }; use transform::{MirPass, MirSource}; From 5846f0e03a4ab3ed36ee0ad09ff3c5ddd9996b13 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 15 Dec 2018 11:29:52 +0100 Subject: [PATCH 21/28] rebase fallout --- src/librustc/ty/context.rs | 7 +---- src/librustc_mir/build/matches/test.rs | 8 +++--- src/librustc_mir/hair/pattern/_match.rs | 34 +++++++++++++++++-------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 108fcc1bd3f21..dfeab9715cc01 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1745,12 +1745,7 @@ impl<'a, 'tcx> Lift<'tcx> for Goal<'a> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } + Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) } } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 3d960a2dd288a..aae3de68aaae0 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -658,7 +658,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - (&TestKind::Range(range), &PatternKind::Constant { ref value }) => { + (&TestKind::Range(range), &PatternKind::Constant { value }) => { if self.const_range_contains(range, value) == Some(false) { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. @@ -787,7 +787,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn const_range_contains( &self, range: PatternRange<'tcx>, - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, ) -> Option { use std::cmp::Ordering::*; @@ -807,9 +807,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn values_not_contained_in_range( &self, range: PatternRange<'tcx>, - indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, + indices: &FxHashMap, usize>, ) -> Option { - for val in indices.keys() { + for &val in indices.keys() { if self.const_range_contains(range, val)? { return Some(false); } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index dc7331a2cd92d..b25d47b390175 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -223,7 +223,7 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { assert_eq!(t, u); ConstValue::ScalarPair( Scalar::Ptr(p), - n.val.try_to_scalar().unwrap(), + n.map_evaluated(|val| val.val.try_to_scalar()).unwrap(), ) }, // fat pointers stay the same @@ -251,11 +251,10 @@ impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> { subpattern: Pattern { ty: rty, span: pat.span, - kind: box PatternKind::Constant { value: Const::from_const_value( - self.tcx, - self.fold_const_value_deref(*val, rty, crty), - rty, - ) }, + kind: box PatternKind::Constant { value: Const { + val: self.fold_const_value_deref(val, rty, crty), + ty: rty, + } }, } } } @@ -1396,7 +1395,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, fn slice_pat_covered_by_const<'tcx>( tcx: TyCtxt<'_, 'tcx, '_>, _span: Span, - const_val: &ty::Const<'tcx>, + const_val: ty::Const<'tcx>, prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>] @@ -1751,12 +1750,27 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { - ty::TyKind::Array(t, n) => (value.to_ptr(), n.unwrap_usize(cx.tcx), t), + let (opt_ptr, n, ty) = match value.ty.sty { + ty::TyKind::Array(t, n) => { + match value.val { + ConstValue::ByRef(id, alloc, offset) => ( + Some((Pointer::new(id, offset), alloc)), + n.unwrap_usize(cx.tcx), + t, + ), + _ => span_bug!( + pat.span, + "array pattern is {:?}", value, + ), + } + }, ty::TyKind::Slice(t) => { match value.val { ConstValue::ScalarPair(ptr, n) => ( - ptr.to_ptr().ok(), + ptr.to_ptr().ok().map(|ptr| ( + ptr, + cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), + )), n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, t, ), From 65a55be47540ff0d06c01aba65d3ca60f23bbe38 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 23 Dec 2018 14:08:04 +0100 Subject: [PATCH 22/28] Git is drunk --- src/librustc/ty/context.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index dfeab9715cc01..ce9be4e84054a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1730,12 +1730,7 @@ impl<'a, 'tcx> Lift<'tcx> for Region<'a> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } + Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) } } @@ -1745,7 +1740,12 @@ impl<'a, 'tcx> Lift<'tcx> for Goal<'a> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } - Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } } } From 88105c204850b02f9b2dea1e280517d3bc65d10b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 27 Dec 2018 15:21:47 +0100 Subject: [PATCH 23/28] what is going on? --- src/librustc/ty/context.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ce9be4e84054a..dfeab9715cc01 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1730,7 +1730,12 @@ impl<'a, 'tcx> Lift<'tcx> for Region<'a> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } - Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } } } @@ -1740,12 +1745,7 @@ impl<'a, 'tcx> Lift<'tcx> for Goal<'a> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } + Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) } } From 598b8f504c446e59d358e85030eebc3b9644fbec Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 28 Dec 2018 12:55:26 +0100 Subject: [PATCH 24/28] Properly lift `Allocations` --- src/librustc/ty/context.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index dfeab9715cc01..8ecaa42a2e91d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1811,15 +1811,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a LazyConst<'a> { impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { type Lifted = &'tcx mir::interpret::Allocation; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } + assert!(tcx.global_interners.arena.in_arena(*self as *const _)); + Some(unsafe { mem::transmute(*self) }) } } From c4366378ebcbe0a6470d936422bcd31cebf7cbfe Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 28 Dec 2018 20:30:06 +0100 Subject: [PATCH 25/28] Macrofy more `Lift` impls --- src/librustc/ty/context.rs | 248 +++++++------------------------------ 1 file changed, 48 insertions(+), 200 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8ecaa42a2e91d..26f0ff0ffa265 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1709,104 +1709,63 @@ pub trait Lift<'tcx>: fmt::Debug { fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option; } -impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { - type Lifted = Ty<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} -impl<'a, 'tcx> Lift<'tcx> for Region<'a> { - type Lifted = Region<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for Goal<'a> { - type Lifted = Goal<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); +macro_rules! nop_lift { + ($ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift<'tcx> for $ty { + type Lifted = $lifted; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); + } + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } + } } - Some(tcx.intern_const_alloc(mir::interpret::Allocation::clone(self))) - } + }; } -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>( - &self, - tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None +macro_rules! nop_list_lift { + ($ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { + type Lifted = &'tcx List<$lifted>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + if self.is_empty() { + return Some(List::empty()); + } + if tcx.interners.arena.in_arena(*self as *const _) { + return Some(unsafe { mem::transmute(*self) }); + } + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } + } } - } + }; } -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>( - &self, - tcx: TyCtxt<'b, 'gcx, 'tcx>, - ) -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } +nop_lift!{Ty<'a> => Ty<'tcx>} +nop_lift!{Region<'a> => Region<'tcx>} +nop_lift!{Goal<'a> => Goal<'tcx>} +nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>} - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} +nop_list_lift!{Goal<'a> => Goal<'tcx>} +nop_list_lift!{Clause<'a> => Clause<'tcx>} +nop_list_lift!{Ty<'a> => Ty<'tcx>} +nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>} +nop_list_lift!{Predicate<'a> => Predicate<'tcx>} +nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo} +nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>} -impl<'a, 'tcx> Lift<'tcx> for &'a LazyConst<'a> { - type Lifted = &'tcx LazyConst<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx LazyConst<'tcx>> { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} +// this is the impl for `&'a Substs<'a>` +nop_list_lift!{Kind<'a> => Kind<'tcx>} impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { type Lifted = &'tcx mir::interpret::Allocation; @@ -1816,117 +1775,6 @@ impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { } } -impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { - type Lifted = &'tcx Substs<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { - if self.len() == 0 { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(&self[..] as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.len() == 0 { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx List>> { - if self.is_empty() { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for &'a List { - type Lifted = &'tcx List; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - if self.len() == 0 { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - -impl<'a, 'tcx> Lift<'tcx> for &'a List> { - type Lifted = &'tcx List>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - if self.len() == 0 { - return Some(List::empty()); - } - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - pub mod tls { use super::{GlobalCtxt, TyCtxt}; From 8856f1e67be0ef4de8cdbd174d703a87391d509d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 28 Dec 2018 20:45:51 +0100 Subject: [PATCH 26/28] Remove unused function --- src/librustc/ty/context.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 26f0ff0ffa265..74fa5363fb2f6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1061,14 +1061,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_arenas.adt_def.alloc(def) } - pub fn alloc_byte_array(self, bytes: &[u8]) -> &'gcx [u8] { - if bytes.is_empty() { - &[] - } else { - self.global_interners.arena.alloc_slice(bytes) - } - } - pub fn intern_const_alloc( self, alloc: Allocation, From 99a5c59403697d127a0d305503c5ae51fb3fc080 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 28 Dec 2018 21:09:47 +0100 Subject: [PATCH 27/28] Check the correct arena --- src/libarena/lib.rs | 5 +++++ src/librustc/ty/context.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b40e905620de9..9f9ded51e37ee 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -119,6 +119,11 @@ impl Default for TypedArena { } impl TypedArena { + pub fn in_arena(&self, ptr: *const T) -> bool { + let ptr = ptr as *const T as *mut T; + + self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end()) + } /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 74fa5363fb2f6..6c377941dad19 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1762,7 +1762,7 @@ nop_list_lift!{Kind<'a> => Kind<'tcx>} impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { type Lifted = &'tcx mir::interpret::Allocation; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - assert!(tcx.global_interners.arena.in_arena(*self as *const _)); + assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _)); Some(unsafe { mem::transmute(*self) }) } } From 0235971e35ef6ffa5851d1899ecb6f157446bb64 Mon Sep 17 00:00:00 2001 From: tcullum-gpsw <38704262+tcullum-gpsw@users.noreply.github.com> Date: Fri, 4 Jan 2019 13:36:59 -0800 Subject: [PATCH 28/28] Change camel case warning to upper camel case Rust structs should be named in upper camel case aka PascalCase. "Upper camel case" was decided upon as the preferred phrase over PascalCase per: https://github.com/rust-lang/rfcs/pull/2389 --- .../src/lints/listing/warn-by-default.md | 2 +- src/librustc_lint/nonstandard_style.rs | 6 ++- .../lint/lint-group-nonstandard-style.stderr | 4 +- src/test/ui/lint/lint-non-camel-case-types.rs | 22 +++++----- .../ui/lint/lint-non-camel-case-types.stderr | 42 +++++++++---------- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index b01aed0915d08..13ffa60ff4fb0 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -163,7 +163,7 @@ struct s; This will produce: ```text -warning: type `s` should have a camel case name such as `S` +warning: type `s` should have an upper camel case name such as `S` --> src/main.rs:1:1 | 1 | struct s; diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 2694a04b94ce4..7eca5867bd3b2 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -89,9 +89,11 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { let c = to_camel_case(&name.as_str()); let m = if c.is_empty() { - format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name) + format!("{} `{}` should have an upper camel case name such as + `CamelCase`", sort, name) } else { - format!("{} `{}` should have a camel case name such as `{}`", sort, name, c) + format!("{} `{}` should have an upper camel case name such as + `{}`", sort, name, c) }; cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m); } diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index d85ca7811d01e..780b4d70aae7f 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -1,7 +1,7 @@ -warning: type `snake_case` should have a camel case name such as `SnakeCase` +warning: type `snake_case` should have an upper camel case name such as `SnakeCase` --> $DIR/lint-group-nonstandard-style.rs:22:9 | -LL | struct snake_case; //~ WARN should have a camel +LL | struct snake_case; //~ WARN should have an upper camel | ^^^^^^^^^^^^^^^^^^ | note: lint level defined here diff --git a/src/test/ui/lint/lint-non-camel-case-types.rs b/src/test/ui/lint/lint-non-camel-case-types.rs index 436763b831687..15ebd0171c8fc 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.rs +++ b/src/test/ui/lint/lint-non-camel-case-types.rs @@ -2,31 +2,31 @@ #![allow(dead_code)] struct ONE_TWO_THREE; -//~^ ERROR type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree` +//~^ ERROR type `ONE_TWO_THREE` should have an upper camel case name such as `OneTwoThree` -struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo` +struct foo { //~ ERROR type `foo` should have an upper camel case name such as `Foo` bar: isize, } -enum foo2 { //~ ERROR type `foo2` should have a camel case name such as `Foo2` +enum foo2 { //~ ERROR type `foo2` should have an upper camel case name such as `Foo2` Bar } -struct foo3 { //~ ERROR type `foo3` should have a camel case name such as `Foo3` +struct foo3 { //~ ERROR type `foo3` should have an upper camel case name such as `Foo3` bar: isize } -type foo4 = isize; //~ ERROR type `foo4` should have a camel case name such as `Foo4` +type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name such as `Foo4` enum Foo5 { - bar //~ ERROR variant `bar` should have a camel case name such as `Bar` + bar //~ ERROR variant `bar` should have an upper camel case name such as `Bar` } -trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6` +trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name such as `Foo6` fn dummy(&self) { } } -fn f(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty` +fn f(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name such as `Ty` #[repr(C)] struct foo7 { @@ -35,10 +35,10 @@ struct foo7 { struct X86_64; -struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64` +struct X86__64; //~ ERROR type `X86__64` should have an upper camel case name such as `X86_64` -struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123` +struct Abc_123; //~ ERROR type `Abc_123` should have an upper camel case name such as `Abc123` -struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3` +struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have an upper camel case name such as `A1B2C3` fn main() { } diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr index 31a8555977116..7d4faa0694405 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.stderr +++ b/src/test/ui/lint/lint-non-camel-case-types.stderr @@ -1,4 +1,4 @@ -error: type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree` +error: type `ONE_TWO_THREE` should have an upper camel case name such as `OneTwoThree` --> $DIR/lint-non-camel-case-types.rs:4:1 | LL | struct ONE_TWO_THREE; @@ -10,72 +10,72 @@ note: lint level defined here LL | #![forbid(non_camel_case_types)] | ^^^^^^^^^^^^^^^^^^^^ -error: type `foo` should have a camel case name such as `Foo` +error: type `foo` should have an upper camel case name such as `Foo` --> $DIR/lint-non-camel-case-types.rs:7:1 | -LL | / struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo` +LL | / struct foo { //~ ERROR type `foo` should have an upper camel case name such as `Foo` LL | | bar: isize, LL | | } | |_^ -error: type `foo2` should have a camel case name such as `Foo2` +error: type `foo2` should have an upper camel case name such as `Foo2` --> $DIR/lint-non-camel-case-types.rs:11:1 | -LL | / enum foo2 { //~ ERROR type `foo2` should have a camel case name such as `Foo2` +LL | / enum foo2 { //~ ERROR type `foo2` should have an upper camel case name such as `Foo2` LL | | Bar LL | | } | |_^ -error: type `foo3` should have a camel case name such as `Foo3` +error: type `foo3` should have an upper camel case name such as `Foo3` --> $DIR/lint-non-camel-case-types.rs:15:1 | -LL | / struct foo3 { //~ ERROR type `foo3` should have a camel case name such as `Foo3` +LL | / struct foo3 { //~ ERROR type `foo3` should have an upper camel case name such as `Foo3` LL | | bar: isize LL | | } | |_^ -error: type `foo4` should have a camel case name such as `Foo4` +error: type `foo4` should have an upper camel case name such as `Foo4` --> $DIR/lint-non-camel-case-types.rs:19:1 | -LL | type foo4 = isize; //~ ERROR type `foo4` should have a camel case name such as `Foo4` +LL | type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name such as `Foo4` | ^^^^^^^^^^^^^^^^^^ -error: variant `bar` should have a camel case name such as `Bar` +error: variant `bar` should have an upper camel case name such as `Bar` --> $DIR/lint-non-camel-case-types.rs:22:5 | -LL | bar //~ ERROR variant `bar` should have a camel case name such as `Bar` +LL | bar //~ ERROR variant `bar` should have an upper camel case name such as `Bar` | ^^^ -error: trait `foo6` should have a camel case name such as `Foo6` +error: trait `foo6` should have an upper camel case name such as `Foo6` --> $DIR/lint-non-camel-case-types.rs:25:1 | -LL | / trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6` +LL | / trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name such as `Foo6` LL | | fn dummy(&self) { } LL | | } | |_^ -error: type parameter `ty` should have a camel case name such as `Ty` +error: type parameter `ty` should have an upper camel case name such as `Ty` --> $DIR/lint-non-camel-case-types.rs:29:6 | -LL | fn f(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty` +LL | fn f(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name such as `Ty` | ^^ -error: type `X86__64` should have a camel case name such as `X86_64` +error: type `X86__64` should have an upper camel case name such as `X86_64` --> $DIR/lint-non-camel-case-types.rs:38:1 | -LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64` +LL | struct X86__64; //~ ERROR type `X86__64` should have an upper camel case name such as `X86_64` | ^^^^^^^^^^^^^^^ -error: type `Abc_123` should have a camel case name such as `Abc123` +error: type `Abc_123` should have an upper camel case name such as `Abc123` --> $DIR/lint-non-camel-case-types.rs:40:1 | -LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123` +LL | struct Abc_123; //~ ERROR type `Abc_123` should have an upper camel case name such as `Abc123` | ^^^^^^^^^^^^^^^ -error: type `A1_b2_c3` should have a camel case name such as `A1B2C3` +error: type `A1_b2_c3` should have an upper camel case name such as `A1B2C3` --> $DIR/lint-non-camel-case-types.rs:42:1 | -LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3` +LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have an upper camel case name such as `A1B2C3` | ^^^^^^^^^^^^^^^^ error: aborting due to 11 previous errors