Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions compiler/rustc_const_eval/src/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,23 @@ where

// Check the qualifs of the value of `const` items.
let uneval = match constant.const_ {
Const::Ty(_, ct) => match ct.kind() {
Const::Ty(ty, ct) => match ct.kind() {
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None,
// Alias consts in MIR bodies don't have associated MIR (e.g. `type const`).
ty::ConstKind::Alias(_, _) => None,
// FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly
// strict, and if instead we should be doing some kind of value-based analysis.
ty::ConstKind::Value(_) => None,
ty::ConstKind::Value(val) => {
if let Some(adt_def) = ty.ty_adt_def()
&& !adt_def.is_union()
&& Q::is_structural_in_adt_value(cx, adt_def)
&& val.destructure_adt_const().fields.is_empty()
{
return false;
} else {
None
}
}
_ => bug!(
"expected ConstKind::Param, ConstKind::Value, ConstKind::Alias, or ConstKind::Error here, found {:?}",
ct
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2364,7 +2364,12 @@ impl Expr<'_> {
ExprKind::Path(qpath) => {
match qpath {
QPath::Resolved(_, Path { res: Res::Def(def_kind, _), .. }) => match def_kind {
DefKind::Const | DefKind::ConstParam | DefKind::AssocConst => true,
DefKind::Const
| DefKind::ConstParam
| DefKind::AssocConst
| DefKind::Fn
| DefKind::AssocFn
| DefKind::Ctor(..) => true,

DefKind::Mod
| DefKind::Struct
Expand All @@ -2377,10 +2382,7 @@ impl Expr<'_> {
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::TyParam
| DefKind::Fn
| DefKind::Static { .. }
| DefKind::Ctor(..)
| DefKind::AssocFn
| DefKind::Macro(_)
| DefKind::ExternCrate
| DefKind::Use
Expand Down
35 changes: 19 additions & 16 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, Node, QPath, is_range_literal};
Expand Down Expand Up @@ -102,7 +102,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::ConstBlock(..) => return None,
hir::ExprKind::Path(qpath) => {
let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
if let Res::Def(DefKind::Const | DefKind::AssocConst, _) = res {
if let Res::Def(
DefKind::Const
| DefKind::AssocConst
| DefKind::ConstParam
| DefKind::Fn
| DefKind::AssocFn
| DefKind::Ctor(..),
_,
)
| Res::SelfCtor(_) = res
{
return None;
}
}
Expand Down Expand Up @@ -138,20 +148,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If someone calls a const fn or constructs a const value, they can extract that
// out into a separate constant (or a const block in the future), so we check that
// to tell them that in the diagnostic. Does not affect typeck.
let is_constable = match element.kind {
hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
traits::IsConstable::Fn
}
_ => traits::IsConstable::No,
},
hir::ExprKind::Path(qpath) => {
match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
_ => traits::IsConstable::No,
}
}
_ => traits::IsConstable::No,
let is_constable = if let hir::ExprKind::Call(func, _args) = element.kind
&& let ty::FnDef(def_id, _) = *self.node_ty(func.hir_id).kind()
&& self.tcx.is_stable_const_fn(def_id)
{
true
} else {
false
};

let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,11 @@ pub enum ExprKind<'tcx> {
},
/// An ADT constructor, e.g. `Foo {x: 1, y: 2}`.
Adt(Box<AdtExpr<'tcx>>),
/// An enum variant unit constructor, e.g. `Option::<T>::None`.
UnitEnum {
variant_index: VariantIdx,
user_ty: UserTy<'tcx>,
},
/// A type ascription on a place.
PlaceTypeAscription {
source: ExprId,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
visitor.visit_expr(&visitor.thir()[base.base]);
}
}
UnitEnum { .. } => {}
PlaceTypeAscription { source, user_ty: _, user_ty_span: _ }
| ValueTypeAscription { source, user_ty: _, user_ty_span: _ } => {
visitor.visit_expr(&visitor.thir()[source])
Expand Down
15 changes: 2 additions & 13 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,9 @@ pub enum ObligationCauseCode<'tcx> {
SizedCoroutineInterior(LocalDefId),
/// `[expr; N]` requires `type_of(expr): Copy`.
RepeatElementCopy {
/// If element is a `const fn` or const ctor we display a help message suggesting
/// If element is a call to a `const fn` we display a help message suggesting
/// to move it to a new `const` item while saying that `T` doesn't implement `Copy`.
is_constable: IsConstable,
is_constable: bool,

/// Span of the repeat element.
///
Expand Down Expand Up @@ -434,17 +434,6 @@ pub enum ObligationCauseCode<'tcx> {
},
}

/// Whether a value can be extracted into a const.
/// Used for diagnostics around array repeat expressions.
#[derive(Copy, Clone, Debug, PartialEq, Eq, StableHash, TyEncodable, TyDecodable)]
pub enum IsConstable {
No,
/// Call to a const fn
Fn,
/// Use of a const ctor
Ctor,
}

/// The 'location' at which we try to perform HIR-based wf checking.
/// This information is used to obtain an `hir::Ty`, which
/// we can walk in order to obtain precise spans for any
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ TrivialTypeTraversalImpls! {
crate::mir::SourceScopeLocalData,
crate::mir::SwitchTargets,
crate::mir::WithRetag,
crate::traits::IsConstable,
crate::traits::OverflowError,
crate::ty::AdtKind,
crate::ty::AssocItem,
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir_build/src/builder/custom/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ macro_rules! parse_by_kind {
$self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) &&
adt_def.variants()[*variant_index].name == rustc_span::sym::$variant
} => $variant_expr,

ExprKind::UnitEnum { variant_index, .. } if
let Some(adt_def) = expr.ty.ty_adt_def() &&
$self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) &&
adt_def.variants()[*variant_index].name == rustc_span::sym::$variant
=> $variant_expr,
)*
$(
$pat $(if $guard)? => $expr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
| ExprKind::ZstLiteral { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::ConstParam { .. }
| ExprKind::ConstBlock { .. } => {
Ok(Operand::Constant(Box::new(
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_mir_build/src/builder/expr/as_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ pub(crate) fn as_constant_inner<'tcx>(

ConstOperand { span, user_ty, const_ }
}
ExprKind::UnitEnum { variant_index, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta);

let val = ty::ValTree::from_branches(
tcx,
[ty::Const::new_value(
tcx,
ty::ValTree::from_scalar_int(tcx, ty::ScalarInt::from(variant_index.as_u32())),
tcx.types.u32,
)],
);
let const_ = Const::Ty(expr.ty, ty::Const::new_value(tcx, val, expr.ty));

ConstOperand { span, user_ty, const_ }
}
ExprKind::NamedConst { def_id, args, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta);
let uneval = mir::UnevaluatedConst::new(def_id, args);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Array { .. }
| ExprKind::Tuple { .. }
| ExprKind::Adt { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::Closure { .. }
| ExprKind::Unary { .. }
| ExprKind::Binary { .. }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
| ExprKind::ZstLiteral { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::ConstParam { .. }
| ExprKind::ConstBlock { .. }
| ExprKind::StaticRef { .. } => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/expr/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ impl Category {
| ExprKind::Literal { .. }
| ExprKind::NonHirLiteral { .. }
| ExprKind::ZstLiteral { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::ConstParam { .. }
| ExprKind::StaticRef { .. }
| ExprKind::NamedConst { .. } => Some(Category::Constant),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
| ExprKind::ZstLiteral { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::ConstParam { .. }
| ExprKind::ThreadLocalRef(_)
| ExprKind::StaticRef { .. }
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/builder/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Literal { .. }
| ExprKind::NonHirLiteral { .. }
| ExprKind::ZstLiteral { .. }
| ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]),
| ExprKind::NamedConst { .. }
| ExprKind::UnitEnum { .. } => self.as_constant(&self.thir[value]),

other => {
use crate::diagnostics::ConstContinueNotMonomorphicConstReason as Reason;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {

ExprKind::RawBorrow { .. }
| ExprKind::Adt { .. }
| ExprKind::UnitEnum { .. }
| ExprKind::Array { .. }
| ExprKind::Binary { .. }
| ExprKind::Block { .. }
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1517,14 +1517,16 @@ impl<'tcx> ThirBuildCx<'tcx> {
match ty.kind() {
// A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case.
ty::Adt(adt_def, args) => ExprKind::Adt(Box::new(AdtExpr {
adt_def: *adt_def,
variant_index: adt_def.variant_index_with_ctor_id(def_id),
args: *args,
user_ty,
fields: Box::new([]),
base: AdtExprBase::None,
})),
ty::Adt(adt_def, _) => {
if adt_def.is_struct() {
ExprKind::ZstLiteral { user_ty }
} else {
ExprKind::UnitEnum {
variant_index: adt_def.variant_index_with_ctor_id(def_id),
user_ty,
}
}
}
_ => bug!("unexpected ty: {:?}", ty),
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
// These evaluate to a value.
RawBorrow { .. }
| Adt { .. }
| UnitEnum { .. }
| Array { .. }
| Binary { .. }
| Block { .. }
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir_build/src/thir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
self.print_adt_expr(&**adt_expr, depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
UnitEnum { variant_index, user_ty } => {
print_indented!(self, "Adt {", depth_lvl);
print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 1);
print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
PlaceTypeAscription { source, user_ty, user_ty_span } => {
print_indented!(self, "PlaceTypeAscription {", depth_lvl);
print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use rustc_hir::{
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::ImplSource;
use rustc_middle::middle::privacy::Level;
use rustc_middle::traits::IsConstable;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::print::{
Expand Down Expand Up @@ -4170,9 +4169,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
"the `Copy` trait is required because this value will be copied for each element of the array",
);
let sm = tcx.sess.source_map();
if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
&& let Ok(_) = sm.span_to_snippet(elt_span)
{
if is_constable && let Ok(_) = sm.span_to_snippet(elt_span) {
err.multipart_suggestion(
"create an inline `const` block",
vec![
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_ty_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ fn recurse_build<'tcx>(
let val = ty::ValTree::from_scalar_int(tcx, lit);
ty::Const::new_value(tcx, val, node.ty)
}
&ExprKind::UnitEnum { variant_index, user_ty: _ } => {
let val = ty::ValTree::from_branches(
tcx,
[ty::Const::new_value(
tcx,
ty::ValTree::from_scalar_int(tcx, ty::ScalarInt::from(variant_index.as_u32())),
tcx.types.u32,
)],
);
ty::Const::new_value(tcx, val, node.ty)
}
&ExprKind::ZstLiteral { user_ty: _ } => ty::Const::zero_sized(tcx, node.ty),
&ExprKind::NamedConst { def_id, args, user_ty: _ } => {
let kind = match tcx.def_kind(def_id) {
Expand Down Expand Up @@ -308,6 +319,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
| thir::ExprKind::Array { .. }
| thir::ExprKind::Tuple { .. }
| thir::ExprKind::Adt(_)
| thir::ExprKind::UnitEnum { .. }
| thir::ExprKind::PlaceTypeAscription { .. }
| thir::ExprKind::ValueTypeAscription { .. }
| thir::ExprKind::PlaceUnwrapUnsafeBinder { .. }
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
_2 = move _3;
StorageDead(_3);
StorageLive(_4);
_4 = Option::<Box<u32>>::None;
_4 = const Option::<Box<u32>>::None;
StorageLive(_5);
StorageLive(_6);
_6 = move _4;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() -> () {
_2 = move _3;
StorageDead(_3);
StorageLive(_4);
_4 = Option::<Box<u32>>::None;
_4 = const Option::<Box<u32>>::None;
FakeRead(ForLet(None), _4);
AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] });
StorageLive(_5);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
+ _9 = const false;
StorageLive(_1);
StorageLive(_2);
_2 = HasDrop;
_2 = const HasDrop;
StorageLive(_3);
_3 = DropAllocator;
_3 = const DropAllocator;
_1 = Box::<HasDrop, DropAllocator>::new_in(move _2, move _3) -> [return: bb1, unwind: bb11];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
}

bb3: {
_0 = Option::<String>::None;
_0 = const Option::<String>::None;
goto -> bb4;
}

Expand Down
Loading
Loading