From 17026ee23f536c0d0d1acb090fe62ac2fdd010f5 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 14 Aug 2021 01:18:44 +0100 Subject: [PATCH 1/2] Fix region issues when using inline const block --- compiler/rustc_middle/src/ty/consts.rs | 22 ++++++++++++++++++- compiler/rustc_mir_build/src/thir/cx/expr.rs | 7 +++--- .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- compiler/rustc_typeck/src/collect/type_of.rs | 10 +++++++-- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index c78151271c171..1e8044047f655 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -35,9 +35,26 @@ impl<'tcx> Const<'tcx> { Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id)) } + /// Similar to `from_anon_const`, but with regions erased (suitable for MIR). + pub fn from_anon_const_erased(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + Self::from_opt_const_arg_anon_const_maybe_erase( + tcx, + ty::WithOptConstParam::unknown(def_id), + true, + ) + } + pub fn from_opt_const_arg_anon_const( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, + ) -> &'tcx Self { + Self::from_opt_const_arg_anon_const_maybe_erase(tcx, def, false) + } + + fn from_opt_const_arg_anon_const_maybe_erase( + tcx: TyCtxt<'tcx>, + def: ty::WithOptConstParam, + erase: bool, ) -> &'tcx Self { debug!("Const::from_anon_const(def={:?})", def); @@ -53,7 +70,10 @@ impl<'tcx> Const<'tcx> { let expr = &tcx.hir().body(body_id).value; - let ty = tcx.type_of(def.def_id_for_type_of()); + let mut ty = tcx.type_of(def.def_id_for_type_of()); + if erase { + ty = tcx.erase_regions_ty(ty); + } let lit_input = match expr.kind { hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c3908ddd4fbe8..4586e5e7c0732 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -484,7 +484,8 @@ impl<'tcx> Cx<'tcx> { hir::InlineAsmOperand::Const { ref anon_const } => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let value = + ty::Const::from_anon_const_erased(self.tcx, anon_const_def_id); let span = self.tcx.hir().span(anon_const.hir_id); InlineAsmOperand::Const { value, span } @@ -563,14 +564,14 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::ConstBlock(ref anon_const) => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let value = ty::Const::from_anon_const_erased(self.tcx, anon_const_def_id); ExprKind::ConstBlock { value } } // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { let count_def_id = self.tcx.hir().local_def_id(count.hir_id); - let count = ty::Const::from_anon_const(self.tcx, count_def_id); + let count = ty::Const::from_anon_const_erased(self.tcx, count_def_id); ExprKind::Repeat { value: self.mirror_expr(v), count } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index dd265d881e6c4..41e1d736e80b7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -544,7 +544,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let (lit, neg) = match expr.kind { hir::ExprKind::ConstBlock(ref anon_const) => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let value = ty::Const::from_anon_const_erased(self.tcx, anon_const_def_id); return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; } hir::ExprKind::Lit(ref lit) => (lit, false), diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index e63c3346e02b1..0e42a68401e8f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -454,7 +454,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); - match parent_node { + let ty = match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) if constant.hir_id == hir_id => @@ -497,7 +497,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { DUMMY_SP, &format!("unexpected const parent in type_of(): {:?}", x), ), - } + }; + + // Typeck doesn't expect erased regions to be returned from `type_of`. + tcx.fold_regions(ty, &mut false, |r, _| match r { + ty::ReErased => tcx.lifetimes.re_static, + _ => r, + }) } Node::GenericParam(param) => match ¶m.kind { From f6375f8321c7f607628bee4ad0cdb5c72a6afce7 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 14 Aug 2021 04:09:30 +0100 Subject: [PATCH 2/2] Add test for issue 78174 --- src/test/ui/inline-const/const-expr-lifetime.rs | 11 +++++++++++ .../ui/inline-const/const-match-pat-lifetime.rs | 13 +++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/inline-const/const-expr-lifetime.rs create mode 100644 src/test/ui/inline-const/const-match-pat-lifetime.rs diff --git a/src/test/ui/inline-const/const-expr-lifetime.rs b/src/test/ui/inline-const/const-expr-lifetime.rs new file mode 100644 index 0000000000000..bc6488a2921f2 --- /dev/null +++ b/src/test/ui/inline-const/const-expr-lifetime.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(inline_const)] + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" + +fn main() { + let foo = const { "foo" }; + assert_eq!(foo, "foo"); +} diff --git a/src/test/ui/inline-const/const-match-pat-lifetime.rs b/src/test/ui/inline-const/const-match-pat-lifetime.rs new file mode 100644 index 0000000000000..af8362c10960b --- /dev/null +++ b/src/test/ui/inline-const/const-match-pat-lifetime.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(inline_const)] + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" + +fn main() { + match "foo" { + const { concat!("fo", "o") } => (), + _ => unreachable!(), + } +}