Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 11 pull requests #70343

Merged
merged 50 commits into from
Mar 24, 2020
Merged
Changes from 10 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5b66f27
Use `const_eval_limit` instead of infinite loop detector
ecstatic-morse Mar 17, 2020
e15c486
Remove infinite loop detector
ecstatic-morse Mar 17, 2020
044dc6e
Update const-eval tests
ecstatic-morse Mar 17, 2020
2daaf2b
replace some adhoc logic with article_and_descr
mark-i-m Mar 16, 2020
99ae428
Improve E0308 error message wording
DeeDeeG Mar 21, 2020
1661a0a
convert a couple more errors
mark-i-m Mar 22, 2020
cdb2c3c
use static strs
mark-i-m Mar 22, 2020
1e5d81d
Fix invalid suggestion on `&mut` iterators yielding `&` references
tirr-c Mar 22, 2020
82f4a1a
get rid of ConstPropUnsupported; use ZST marker structs instead
RalfJung Mar 22, 2020
d40dff9
the crate and tests
mark-i-m Mar 22, 2020
b5636b8
Rename `TimeLimitReached` -> `StepLimitReached`
ecstatic-morse Mar 22, 2020
bd1df44
Add regression test for #70155.
Mar 22, 2020
cda81da
avoid unsafe code, use upcasting-trait instead (trick by oli)
RalfJung Mar 22, 2020
5e8b795
fix one more test
mark-i-m Mar 22, 2020
410385d
add macro to reduce boilerplate and keep readable messages
RalfJung Mar 23, 2020
e619b85
make sure we are checking the size of the right thing
RalfJung Mar 23, 2020
19e6935
Clean up E0452 explanation
GuillaumeGomez Mar 23, 2020
799b15e
Evaluate repeat expression lengths as late as possible
oli-obk Mar 14, 2020
fa5a15c
Document most methods on `ty::Const`
oli-obk Mar 14, 2020
3f89c38
Inline `const_param_def_id` at its only use site
oli-obk Mar 14, 2020
770be24
Use `DefId`s to identify anon consts when converting from HIR to ty::…
oli-obk Mar 17, 2020
c3b9881
Remove `ReClosureBound`
matthewjasper Mar 11, 2020
f080f94
Add const generics test for all range types.
Mar 23, 2020
9bcd9fe
Address review comments
oli-obk Mar 23, 2020
9fdde0a
Merge tests.
Mar 23, 2020
124ab20
Limit `from_anon_const` to `AnonConst`s.
oli-obk Mar 23, 2020
e75158d
Account for bad placeholder types in where clauses
estebank Mar 23, 2020
5aa15bf
Remove leftover mentions of `from_anon_const`
oli-obk Mar 23, 2020
4f513b5
Split out some impls from rustc::mir into a separate submodule
oli-obk Mar 23, 2020
a7e2641
Move dep_graph to new crate librustc_query_system.
cjgillot Dec 31, 2019
6624dc4
Make librustc_query_system compile.
cjgillot Mar 18, 2020
db7bd5f
Fallout in other crates.
cjgillot Mar 18, 2020
2326ae3
Merge ensure_node_can_be_forced into force_from_dep_node.
cjgillot Mar 20, 2020
3a8bb20
Remove assert_ignored and with_ignore_deps.
cjgillot Mar 20, 2020
d08cc0b
Put extract_def_id back on DepNode.
cjgillot Mar 21, 2020
e0f7b89
Address review.
cjgillot Mar 22, 2020
9f4c888
Fully qualify the path to DepKind.
cjgillot Mar 22, 2020
0f918cb
Move import.
cjgillot Mar 23, 2020
9b1893f
Run rustfmt
oli-obk Mar 23, 2020
9da25d9
Rollup merge of #67761 - cjgillot:split_graph, r=Zoxc
Centril Mar 23, 2020
ee90948
Rollup merge of #69740 - mark-i-m:describe-it-3, r=eddyb
Centril Mar 23, 2020
a73ed5a
Rollup merge of #69981 - oli-obk:const_blocks, r=eddyb
Centril Mar 23, 2020
72c99f2
Rollup merge of #70087 - ecstatic-morse:remove-const-eval-loop-detect…
Centril Mar 23, 2020
7a47df8
Rollup merge of #70242 - DeeDeeG:improve-e0308, r=Dylan-DPC
Centril Mar 23, 2020
ab2817b
Rollup merge of #70264 - tirr-c:issue-69789-mut-suggestion, r=estebank
Centril Mar 23, 2020
3184506
Rollup merge of #70267 - RalfJung:const-prop-unsup, r=oli-obk,wesleyw…
Centril Mar 23, 2020
6c58e01
Rollup merge of #70277 - matthewjasper:remove-closurebound, r=nikomat…
Centril Mar 23, 2020
7cdab7f
Rollup merge of #70283 - CDirkx:regression-test-70155, r=oli-obk
Centril Mar 23, 2020
54db0cf
Rollup merge of #70294 - estebank:bad-placeholder-in-where, r=Centril
Centril Mar 23, 2020
3b8872d
Rollup merge of #70309 - GuillaumeGomez:cleanup-e0452, r=Dylan-DPC
Centril Mar 23, 2020
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
2 changes: 1 addition & 1 deletion src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
@@ -156,7 +156,7 @@ pub struct LitToConstInput<'tcx> {
pub enum LitToConstError {
/// The literal's inferred type did not match the expected `ty` in the input.
/// This is used for graceful error handling (`delay_span_bug`) in
/// type checking (`AstConv::ast_const_to_const`).
/// type checking (`Const::from_anon_const`).
TypeError,
UnparseableFloat,
Reported,
355 changes: 23 additions & 332 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ pub mod mono;
mod query;
pub mod tcx;
pub mod traversal;
mod type_foldable;
pub mod visit;

/// Types for locals
@@ -2046,7 +2047,7 @@ pub enum Rvalue<'tcx> {
Use(Operand<'tcx>),

/// [x; 32]
Repeat(Operand<'tcx>, u64),
Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>),

/// &x or &mut x
Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
@@ -2174,7 +2175,11 @@ impl<'tcx> Debug for Rvalue<'tcx> {

match *self {
Use(ref place) => write!(fmt, "{:?}", place),
Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b),
Repeat(ref a, ref b) => {
write!(fmt, "[{:?}; ", a)?;
pretty_print_const(b, fmt, false)?;
write!(fmt, "]")
}
Len(ref a) => write!(fmt, "Len({:?})", a),
Cast(ref kind, ref place, ref ty) => {
write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind)
@@ -2542,18 +2547,26 @@ impl<'tcx> Debug for Constant<'tcx> {

impl<'tcx> Display for Constant<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use crate::ty::print::PrettyPrinter;
write!(fmt, "const ")?;
ty::tls::with(|tcx| {
let literal = tcx.lift(&self.literal).unwrap();
let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
cx.print_alloc_ids = true;
cx.pretty_print_const(literal, true)?;
Ok(())
})
pretty_print_const(self.literal, fmt, true)
}
}

fn pretty_print_const(
c: &ty::Const<'tcx>,
fmt: &mut Formatter<'_>,
print_types: bool,
) -> fmt::Result {
use crate::ty::print::PrettyPrinter;
ty::tls::with(|tcx| {
let literal = tcx.lift(&c).unwrap();
let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
cx.print_alloc_ids = true;
cx.pretty_print_const(literal, print_types)?;
Ok(())
})
}

impl<'tcx> graph::DirectedGraph for Body<'tcx> {
type Node = BasicBlock;
}
@@ -2651,325 +2664,3 @@ impl Location {
}
}
}

/*
* `TypeFoldable` implementations for MIR types
*/

CloneTypeFoldableAndLiftImpls! {
BlockTailInfo,
MirPhase,
SourceInfo,
FakeReadCause,
RetagKind,
SourceScope,
SourceScopeData,
SourceScopeLocalData,
UserTypeAnnotationIndex,
}

impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::TerminatorKind::*;

let kind = match self.kind {
Goto { target } => Goto { target },
SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
discr: discr.fold_with(folder),
switch_ty: switch_ty.fold_with(folder),
values: values.clone(),
targets: targets.clone(),
},
Drop { ref location, target, unwind } => {
Drop { location: location.fold_with(folder), target, unwind }
}
DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
location: location.fold_with(folder),
value: value.fold_with(folder),
target,
unwind,
},
Yield { ref value, resume, ref resume_arg, drop } => Yield {
value: value.fold_with(folder),
resume,
resume_arg: resume_arg.fold_with(folder),
drop,
},
Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
let dest =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));

Call {
func: func.fold_with(folder),
args: args.fold_with(folder),
destination: dest,
cleanup,
from_hir_call,
}
}
Assert { ref cond, expected, ref msg, target, cleanup } => {
use AssertKind::*;
let msg = match msg {
BoundsCheck { ref len, ref index } => {
BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
}
Overflow(_)
| OverflowNeg
| DivisionByZero
| RemainderByZero
| ResumedAfterReturn(_)
| ResumedAfterPanic(_) => msg.clone(),
};
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
}
GeneratorDrop => GeneratorDrop,
Resume => Resume,
Abort => Abort,
Return => Return,
Unreachable => Unreachable,
FalseEdges { real_target, imaginary_target } => {
FalseEdges { real_target, imaginary_target }
}
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
};
Terminator { source_info: self.source_info, kind }
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
use crate::mir::TerminatorKind::*;

match self.kind {
SwitchInt { ref discr, switch_ty, .. } => {
discr.visit_with(visitor) || switch_ty.visit_with(visitor)
}
Drop { ref location, .. } => location.visit_with(visitor),
DropAndReplace { ref location, ref value, .. } => {
location.visit_with(visitor) || value.visit_with(visitor)
}
Yield { ref value, .. } => value.visit_with(visitor),
Call { ref func, ref args, ref destination, .. } => {
let dest = if let Some((ref loc, _)) = *destination {
loc.visit_with(visitor)
} else {
false
};
dest || func.visit_with(visitor) || args.visit_with(visitor)
}
Assert { ref cond, ref msg, .. } => {
if cond.visit_with(visitor) {
use AssertKind::*;
match msg {
BoundsCheck { ref len, ref index } => {
len.visit_with(visitor) || index.visit_with(visitor)
}
Overflow(_)
| OverflowNeg
| DivisionByZero
| RemainderByZero
| ResumedAfterReturn(_)
| ResumedAfterPanic(_) => false,
}
} else {
false
}
}
Goto { .. }
| Resume
| Abort
| Return
| GeneratorDrop
| Unreachable
| FalseEdges { .. }
| FalseUnwind { .. } => false,
}
}
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.local.visit_with(visitor) || self.projection.visit_with(visitor)
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
folder.tcx().intern_place_elems(&v)
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => Use(op.fold_with(folder)),
Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
Ref(region, bk, ref place) => {
Ref(region.fold_with(folder), bk, place.fold_with(folder))
}
AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)),
Len(ref place) => Len(place.fold_with(folder)),
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
BinaryOp(op, ref rhs, ref lhs) => {
BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
}
CheckedBinaryOp(op, ref rhs, ref lhs) => {
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
}
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
Discriminant(ref place) => Discriminant(place.fold_with(folder)),
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
Aggregate(ref kind, ref fields) => {
let kind = box match **kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
AggregateKind::Tuple => AggregateKind::Tuple,
AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
def,
v,
substs.fold_with(folder),
user_ty.fold_with(folder),
n,
),
AggregateKind::Closure(id, substs) => {
AggregateKind::Closure(id, substs.fold_with(folder))
}
AggregateKind::Generator(id, substs, movablity) => {
AggregateKind::Generator(id, substs.fold_with(folder), movablity)
}
};
Aggregate(kind, fields.fold_with(folder))
}
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => op.visit_with(visitor),
Repeat(ref op, _) => op.visit_with(visitor),
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
AddressOf(_, ref place) => place.visit_with(visitor),
Len(ref place) => place.visit_with(visitor),
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
rhs.visit_with(visitor) || lhs.visit_with(visitor)
}
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref place) => place.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
(match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
AggregateKind::Tuple => false,
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor) || user_ty.visit_with(visitor)
}
AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
}) || fields.visit_with(visitor)
}
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
match *self {
Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
}
}
}

impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::ProjectionElem::*;

match *self {
Deref => Deref,
Field(f, ty) => Field(f, ty.fold_with(folder)),
Index(v) => Index(v.fold_with(folder)),
Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
ConstantIndex { offset, min_length, from_end } => {
ConstantIndex { offset, min_length, from_end }
}
Subslice { from, to, from_end } => Subslice { from, to, from_end },
}
}

fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
use crate::mir::ProjectionElem::*;

match self {
Field(_, ty) => ty.visit_with(visitor),
Index(v) => v.visit_with(visitor),
_ => false,
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Field {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
self.clone()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Constant {
span: self.span,
user_ty: self.user_ty.fold_with(folder),
literal: self.literal.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.literal.visit_with(visitor)
}
}
4 changes: 3 additions & 1 deletion src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
@@ -149,7 +149,9 @@ impl<'tcx> Rvalue<'tcx> {
{
match *self {
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, count) => tcx.mk_array(operand.ty(local_decls, tcx), count),
Rvalue::Repeat(ref operand, count) => {
tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count))
}
Rvalue::Ref(reg, bk, ref place) => {
let place_ty = place.ty(local_decls, tcx).ty;
tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
322 changes: 322 additions & 0 deletions src/librustc/mir/type_foldable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
//! `TypeFoldable` implementations for MIR types
use super::*;
use crate::ty;

CloneTypeFoldableAndLiftImpls! {
BlockTailInfo,
MirPhase,
SourceInfo,
FakeReadCause,
RetagKind,
SourceScope,
SourceScopeData,
SourceScopeLocalData,
UserTypeAnnotationIndex,
}

impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::TerminatorKind::*;

let kind = match self.kind {
Goto { target } => Goto { target },
SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
discr: discr.fold_with(folder),
switch_ty: switch_ty.fold_with(folder),
values: values.clone(),
targets: targets.clone(),
},
Drop { ref location, target, unwind } => {
Drop { location: location.fold_with(folder), target, unwind }
}
DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
location: location.fold_with(folder),
value: value.fold_with(folder),
target,
unwind,
},
Yield { ref value, resume, ref resume_arg, drop } => Yield {
value: value.fold_with(folder),
resume,
resume_arg: resume_arg.fold_with(folder),
drop,
},
Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
let dest =
destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));

Call {
func: func.fold_with(folder),
args: args.fold_with(folder),
destination: dest,
cleanup,
from_hir_call,
}
}
Assert { ref cond, expected, ref msg, target, cleanup } => {
use AssertKind::*;
let msg = match msg {
BoundsCheck { ref len, ref index } => {
BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
}
Overflow(_)
| OverflowNeg
| DivisionByZero
| RemainderByZero
| ResumedAfterReturn(_)
| ResumedAfterPanic(_) => msg.clone(),
};
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
}
GeneratorDrop => GeneratorDrop,
Resume => Resume,
Abort => Abort,
Return => Return,
Unreachable => Unreachable,
FalseEdges { real_target, imaginary_target } => {
FalseEdges { real_target, imaginary_target }
}
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
};
Terminator { source_info: self.source_info, kind }
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
use crate::mir::TerminatorKind::*;

match self.kind {
SwitchInt { ref discr, switch_ty, .. } => {
discr.visit_with(visitor) || switch_ty.visit_with(visitor)
}
Drop { ref location, .. } => location.visit_with(visitor),
DropAndReplace { ref location, ref value, .. } => {
location.visit_with(visitor) || value.visit_with(visitor)
}
Yield { ref value, .. } => value.visit_with(visitor),
Call { ref func, ref args, ref destination, .. } => {
let dest = if let Some((ref loc, _)) = *destination {
loc.visit_with(visitor)
} else {
false
};
dest || func.visit_with(visitor) || args.visit_with(visitor)
}
Assert { ref cond, ref msg, .. } => {
if cond.visit_with(visitor) {
use AssertKind::*;
match msg {
BoundsCheck { ref len, ref index } => {
len.visit_with(visitor) || index.visit_with(visitor)
}
Overflow(_)
| OverflowNeg
| DivisionByZero
| RemainderByZero
| ResumedAfterReturn(_)
| ResumedAfterPanic(_) => false,
}
} else {
false
}
}
Goto { .. }
| Resume
| Abort
| Return
| GeneratorDrop
| Unreachable
| FalseEdges { .. }
| FalseUnwind { .. } => false,
}
}
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.local.visit_with(visitor) || self.projection.visit_with(visitor)
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
folder.tcx().intern_place_elems(&v)
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => Use(op.fold_with(folder)),
Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
Ref(region, bk, ref place) => {
Ref(region.fold_with(folder), bk, place.fold_with(folder))
}
AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)),
Len(ref place) => Len(place.fold_with(folder)),
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
BinaryOp(op, ref rhs, ref lhs) => {
BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
}
CheckedBinaryOp(op, ref rhs, ref lhs) => {
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder))
}
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
Discriminant(ref place) => Discriminant(place.fold_with(folder)),
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
Aggregate(ref kind, ref fields) => {
let kind = box match **kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
AggregateKind::Tuple => AggregateKind::Tuple,
AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
def,
v,
substs.fold_with(folder),
user_ty.fold_with(folder),
n,
),
AggregateKind::Closure(id, substs) => {
AggregateKind::Closure(id, substs.fold_with(folder))
}
AggregateKind::Generator(id, substs, movablity) => {
AggregateKind::Generator(id, substs.fold_with(folder), movablity)
}
};
Aggregate(kind, fields.fold_with(folder))
}
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => op.visit_with(visitor),
Repeat(ref op, _) => op.visit_with(visitor),
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
AddressOf(_, ref place) => place.visit_with(visitor),
Len(ref place) => place.visit_with(visitor),
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
rhs.visit_with(visitor) || lhs.visit_with(visitor)
}
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref place) => place.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
(match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
AggregateKind::Tuple => false,
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor) || user_ty.visit_with(visitor)
}
AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
}) || fields.visit_with(visitor)
}
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
match *self {
Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)),
Operand::Move(ref place) => Operand::Move(place.fold_with(folder)),
Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
}
}
}

impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
use crate::mir::ProjectionElem::*;

match *self {
Deref => Deref,
Field(f, ty) => Field(f, ty.fold_with(folder)),
Index(v) => Index(v.fold_with(folder)),
Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
ConstantIndex { offset, min_length, from_end } => {
ConstantIndex { offset, min_length, from_end }
}
Subslice { from, to, from_end } => Subslice { from, to, from_end },
}
}

fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
use crate::mir::ProjectionElem::*;

match self {
Field(_, ty) => ty.visit_with(visitor),
Index(v) => v.visit_with(visitor),
_ => false,
}
}
}

impl<'tcx> TypeFoldable<'tcx> for Field {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
self.clone()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Constant {
span: self.span,
user_ty: self.user_ty.fold_with(folder),
literal: self.literal.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.literal.visit_with(visitor)
}
}
89 changes: 87 additions & 2 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use self::TyKind::*;
use crate::infer::canonical::Canonical;
use crate::middle::region;
use crate::mir::interpret::ConstValue;
use crate::mir::interpret::Scalar;
use crate::mir::interpret::{LitToConstInput, Scalar};
use crate::mir::Promoted;
use crate::ty::layout::VariantIdx;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
@@ -20,7 +20,7 @@ use polonius_engine::Atom;
use rustc_ast::ast::{self, Ident};
use rustc_data_structures::captures::Captures;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::vec::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, Symbol};
@@ -2275,17 +2275,92 @@ pub struct Const<'tcx> {
static_assert_size!(Const<'_>, 48);

impl<'tcx> Const<'tcx> {
/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self {
debug!("Const::from_anon_const(id={:?})", def_id);

let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

let body_id = match tcx.hir().get(hir_id) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
tcx.def_span(def_id.to_def_id()),
"from_anon_const can only process anonymous constants"
),
};

let expr = &tcx.hir().body(body_id).value;

let ty = tcx.type_of(def_id.to_def_id());

let lit_input = match expr.kind {
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind {
hir::ExprKind::Lit(ref lit) => {
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
}
_ => None,
},
_ => None,
};

if let Some(lit_input) = lit_input {
// If an error occurred, ignore that it's a literal and leave reporting the error up to
// mir.
if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
return c;
} else {
tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const");
}
}

// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
block.expr.as_ref().unwrap()
}
_ => expr,
};

use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
let val = match expr.kind {
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
// Find the name and index of the const parameter by indexing the generics of
// the parent item and construct a `ParamConst`.
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(hir_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)];
let name = tcx.hir().name(hir_id);
ty::ConstKind::Param(ty::ParamConst::new(index, name))
}
_ => ty::ConstKind::Unevaluated(
def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
None,
),
};

tcx.mk_const(ty::Const { val, ty })
}

#[inline]
/// Interns the given value as a constant.
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
}

#[inline]
/// Interns the given scalar as a constant.
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self {
Self::from_value(tcx, ConstValue::Scalar(val), ty)
}

#[inline]
/// Creates a constant with the given integer value and interns it.
pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self {
let size = tcx
.layout_of(ty)
@@ -2295,21 +2370,27 @@ impl<'tcx> Const<'tcx> {
}

#[inline]
/// Creates an interned zst constant.
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
Self::from_scalar(tcx, Scalar::zst(), ty)
}

#[inline]
/// Creates an interned bool constant.
pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> &'tcx Self {
Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool))
}

#[inline]
/// Creates an interned usize constant.
pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> &'tcx Self {
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
}

#[inline]
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
/// contains const generic parameters or pointers).
pub fn try_eval_bits(
&self,
tcx: TyCtxt<'tcx>,
@@ -2323,6 +2404,8 @@ impl<'tcx> Const<'tcx> {
}

#[inline]
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
/// unevaluated constant.
pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> {
let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| {
let param_env_and_substs = param_env.with_reveal_all().and(substs);
@@ -2379,12 +2462,14 @@ impl<'tcx> Const<'tcx> {
}

#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
self.try_eval_bits(tcx, param_env, ty)
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
}

#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
self.eval_bits(tcx, param_env, tcx.types.usize) as u64
}
3 changes: 3 additions & 0 deletions src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -106,6 +106,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}

let count =
self.monomorphize(&count).eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());

bx.write_operand_repeatedly(cg_elem, count, dest)
}

6 changes: 5 additions & 1 deletion src/librustc_mir/borrow_check/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -1986,7 +1986,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}

Rvalue::Repeat(operand, len) => {
if *len > 1 {
// If the length cannot be evaluated we must assume that the length can be larger
// than 1.
// If the length is larger than 1, the repeat expression will need to copy the
// element, so we require the `Copy` trait.
if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
if let Operand::Move(_) = operand {
// While this is located in `nll::typeck` this error is not an NLL error, it's
// a required check to make sure that repeated elements implement `Copy`.
32 changes: 3 additions & 29 deletions src/librustc_mir_build/hair/cx/expr.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use crate::hair::cx::to_ref::ToRef;
use crate::hair::cx::Cx;
use crate::hair::util::UserAnnotatedTyHelpers;
use crate::hair::*;
use rustc::mir::interpret::{ErrorHandled, Scalar};
use rustc::mir::interpret::Scalar;
use rustc::mir::BorrowKind;
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast};
use rustc::ty::subst::{InternalSubsts, SubstsRef};
@@ -406,34 +406,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(

// Now comes the rote stuff:
hir::ExprKind::Repeat(ref v, ref count) => {
let def_id = cx.tcx.hir().local_def_id(count.hir_id);
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
let span = cx.tcx.def_span(def_id);
let count = match cx.tcx.const_eval_resolve(
ty::ParamEnv::reveal_all(),
def_id,
substs,
None,
Some(span),
) {
Ok(cv) => {
if let Some(count) = cv.try_to_bits_for_ty(
cx.tcx,
ty::ParamEnv::reveal_all(),
cx.tcx.types.usize,
) {
count as u64
} else {
bug!("repeat count constant value can't be converted to usize");
}
}
Err(ErrorHandled::Reported) => 0,
Err(ErrorHandled::TooGeneric) => {
let span = cx.tcx.def_span(def_id);
cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");
0
}
};
let count_def_id = cx.tcx.hir().local_def_id(count.hir_id).expect_local();
let count = ty::Const::from_anon_const(cx.tcx, count_def_id);

ExprKind::Repeat { value: v.to_ref(), count }
}
2 changes: 1 addition & 1 deletion src/librustc_mir_build/hair/mod.rs
Original file line number Diff line number Diff line change
@@ -229,7 +229,7 @@ crate enum ExprKind<'tcx> {
},
Repeat {
value: ExprRef<'tcx>,
count: u64,
count: &'tcx Const<'tcx>,
},
Array {
fields: Vec<ExprRef<'tcx>>,
79 changes: 5 additions & 74 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::print;
use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs};
use rustc_hir::{Constness, GenericArg, GenericArgs};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS};
use rustc_session::parse::feature_err;
use rustc_session::Session;
@@ -39,8 +39,6 @@ use std::collections::BTreeSet;
use std::iter;
use std::slice;

use rustc::mir::interpret::LitToConstInput;

#[derive(Debug)]
pub struct PathSeg(pub DefId, pub usize);

@@ -782,7 +780,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into()
let ct_def_id = tcx.hir().local_def_id(ct.value.hir_id).expect_local();
ty::Const::from_anon_const(tcx, ct_def_id).into()
}
_ => unreachable!(),
},
@@ -2775,7 +2774,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.unwrap_or(tcx.types.err)
}
hir::TyKind::Array(ref ty, ref length) => {
let length = self.ast_const_to_const(length, tcx.types.usize);
let length_def_id = tcx.hir().local_def_id(length.hir_id).expect_local();
let length = ty::Const::from_anon_const(tcx, length_def_id);
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
self.normalize_ty(ast_ty.span, array_ty)
}
@@ -2807,75 +2807,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
result_ty
}

/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
pub fn const_param_def_id(&self, expr: &hir::Expr<'_>) -> Option<DefId> {
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
block.expr.as_ref().unwrap()
}
_ => expr,
};

match &expr.kind {
ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
Res::Def(DefKind::ConstParam, did) => Some(did),
_ => None,
},
_ => None,
}
}

pub fn ast_const_to_const(
&self,
ast_const: &hir::AnonConst,
ty: Ty<'tcx>,
) -> &'tcx ty::Const<'tcx> {
debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);

let tcx = self.tcx();
let def_id = tcx.hir().local_def_id(ast_const.hir_id);

let expr = &tcx.hir().body(ast_const.body).value;

let lit_input = match expr.kind {
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind {
hir::ExprKind::Lit(ref lit) => {
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
}
_ => None,
},
_ => None,
};

if let Some(lit_input) = lit_input {
// If an error occurred, ignore that it's a literal and leave reporting the error up to
// mir.
if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
return c;
} else {
tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const");
}
}

let kind = if let Some(def_id) = self.const_param_def_id(expr) {
// Find the name and index of the const parameter by indexing the generics of the
// parent item and construct a `ParamConst`.
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(hir_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)];
let name = tcx.hir().name(hir_id);
ty::ConstKind::Param(ty::ParamConst::new(index, name))
} else {
ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None)
};
tcx.mk_const(ty::Const { val: kind, ty })
}

pub fn impl_trait_ty_to_ty(
&self,
def_id: DefId,
22 changes: 3 additions & 19 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@ use crate::type_error_struct;
use crate::util::common::ErrorReported;

use rustc::middle::lang_items;
use rustc::mir::interpret::ErrorHandled;
use rustc::ty;
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::Ty;
@@ -1008,13 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let count_def_id = tcx.hir().local_def_id(count.hir_id);
let count = if self.const_param_def_id(count).is_some() {
Ok(self.to_const(count, tcx.type_of(count_def_id)))
} else {
tcx.const_eval_poly(count_def_id)
.map(|val| ty::Const::from_value(tcx, val, tcx.type_of(count_def_id)))
};
let count = self.to_const(count);

let uty = match expected {
ExpectHasType(uty) => match uty.kind {
@@ -1042,17 +1035,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if element_ty.references_error() {
return tcx.types.err;
}
match count {
Ok(count) => tcx.mk_ty(ty::Array(t, count)),
Err(ErrorHandled::TooGeneric) => {
self.tcx.sess.span_err(
tcx.def_span(count_def_id),
"array lengths can't depend on generic parameters",
);
tcx.types.err
}
Err(ErrorHandled::Reported) => tcx.types.err,
}

tcx.mk_ty(ty::Array(t, count))
}

fn check_expr_tuple(
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/method/confirm.rs
Original file line number Diff line number Diff line change
@@ -331,7 +331,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
}
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => self.to_ty(ty).into(),
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
self.to_const(&ct.value).into()
}
_ => unreachable!(),
},
12 changes: 4 additions & 8 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -3279,13 +3279,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty
}

/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option<DefId> {
AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value)
}

pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
AstConv::ast_const_to_const(self, ast_c, ty)
pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
let c = self.tcx.hir().local_def_id(ast_c.hir_id).expect_local();
ty::Const::from_anon_const(self.tcx, c)
}

// If the type given by the user has free regions, save it for later, since
@@ -5512,7 +5508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.to_ty(ty).into()
}
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
self.to_const(&ct.value).into()
}
_ => unreachable!(),
},
7 changes: 1 addition & 6 deletions src/test/compile-fail/issue-52443.rs
Original file line number Diff line number Diff line change
@@ -7,10 +7,5 @@ fn main() {
//~^ ERROR `while` is not allowed in a `const`
//~| WARN denote infinite loops with
[(); { for _ in 0usize.. {}; 0}];
//~^ ERROR calls in constants are limited to constant functions
//~| ERROR calls in constants are limited to constant functions
//~| ERROR `for` is not allowed in a `const`
//~| ERROR references in constants may only refer to immutable values
//~| ERROR evaluation of constant value failed
//~| ERROR constant contains unimplemented expression type
//~^ ERROR `for` is not allowed in a `const`
}
1 change: 1 addition & 0 deletions src/test/ui/closures/issue-52437.rs
Original file line number Diff line number Diff line change
@@ -3,4 +3,5 @@ fn main() {
//~^ ERROR: invalid label name `'static`
//~| ERROR: `loop` is not allowed in a `const`
//~| ERROR: type annotations needed
//~| ERROR mismatched types
}
12 changes: 10 additions & 2 deletions src/test/ui/closures/issue-52437.stderr
Original file line number Diff line number Diff line change
@@ -19,7 +19,15 @@ error[E0282]: type annotations needed
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
| ^ consider giving this closure parameter a type

error: aborting due to 3 previous errors
error[E0308]: mismatched types
--> $DIR/issue-52437.rs:2:5
|
LL | fn main() {
| - expected `()` because of default return type
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[(); _]`

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0282, E0658.
Some errors have detailed explanations: E0282, E0308, E0658.
For more information about an error, try `rustc --explain E0282`.
3 changes: 2 additions & 1 deletion src/test/ui/const-generics/issues/issue-61336-1.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

// build-pass

fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; N]
//~^ ERROR array lengths can't depend on generic parameters
}

fn main() {
8 changes: 0 additions & 8 deletions src/test/ui/const-generics/issues/issue-61336-1.stderr
Original file line number Diff line number Diff line change
@@ -6,11 +6,3 @@ LL | #![feature(const_generics)]
|
= note: `#[warn(incomplete_features)]` on by default

error: array lengths can't depend on generic parameters
--> $DIR/issue-61336-1.rs:5:9
|
LL | [x; N]
| ^

error: aborting due to previous error

7 changes: 3 additions & 4 deletions src/test/ui/const-generics/issues/issue-61336-2.rs
Original file line number Diff line number Diff line change
@@ -2,13 +2,12 @@
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; {N}]
//~^ ERROR array lengths can't depend on generic parameters
[x; { N }]
}

fn g<T, const N: usize>(x: T) -> [T; N] {
[x; {N}]
//~^ ERROR array lengths can't depend on generic parameters
[x; { N }]
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
}

fn main() {
22 changes: 12 additions & 10 deletions src/test/ui/const-generics/issues/issue-61336-2.stderr
Original file line number Diff line number Diff line change
@@ -6,17 +6,19 @@ LL | #![feature(const_generics)]
|
= note: `#[warn(incomplete_features)]` on by default

error: array lengths can't depend on generic parameters
--> $DIR/issue-61336-2.rs:5:9
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/issue-61336-2.rs:9:5
|
LL | [x; {N}]
| ^^^

error: array lengths can't depend on generic parameters
--> $DIR/issue-61336-2.rs:10:9
LL | [x; { N }]
| ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
help: consider restricting this type parameter with `T: std::marker::Copy`
--> $DIR/issue-61336-2.rs:8:6
|
LL | [x; {N}]
| ^^^
LL | fn g<T, const N: usize>(x: T) -> [T; N] {
| ^
= note: the `Copy` trait is required because the repeated element will be copied

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
3 changes: 1 addition & 2 deletions src/test/ui/const-generics/issues/issue-61336.rs
Original file line number Diff line number Diff line change
@@ -3,12 +3,11 @@

fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; N]
//~^ ERROR array lengths can't depend on generic parameters
}

fn g<T, const N: usize>(x: T) -> [T; N] {
[x; N]
//~^ ERROR array lengths can't depend on generic parameters
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
}

fn main() {
20 changes: 11 additions & 9 deletions src/test/ui/const-generics/issues/issue-61336.stderr
Original file line number Diff line number Diff line change
@@ -6,17 +6,19 @@ LL | #![feature(const_generics)]
|
= note: `#[warn(incomplete_features)]` on by default

error: array lengths can't depend on generic parameters
--> $DIR/issue-61336.rs:5:9
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/issue-61336.rs:9:5
|
LL | [x; N]
| ^

error: array lengths can't depend on generic parameters
--> $DIR/issue-61336.rs:10:9
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
LL | [x; N]
| ^
help: consider restricting this type parameter with `T: std::marker::Copy`
--> $DIR/issue-61336.rs:8:6
|
LL | fn g<T, const N: usize>(x: T) -> [T; N] {
| ^
= note: the `Copy` trait is required because the repeated element will be copied

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
3 changes: 2 additions & 1 deletion src/test/ui/const-generics/issues/issue-62456.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

// build-pass

fn foo<const N: usize>() {
let _ = [0u64; N + 1];
//~^ ERROR array lengths can't depend on generic parameters
}

fn main() {}
8 changes: 0 additions & 8 deletions src/test/ui/const-generics/issues/issue-62456.stderr
Original file line number Diff line number Diff line change
@@ -6,11 +6,3 @@ LL | #![feature(const_generics)]
|
= note: `#[warn(incomplete_features)]` on by default

error: array lengths can't depend on generic parameters
--> $DIR/issue-62456.rs:5:20
|
LL | let _ = [0u64; N + 1];
| ^^^^^

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/const-generics/issues/issue-62504.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ struct ArrayHolder<const X: usize>([u32; X]);
impl<const X: usize> ArrayHolder<{ X }> {
pub const fn new() -> Self {
ArrayHolder([0; Self::SIZE])
//~^ ERROR: array lengths can't depend on generic parameters
//~^ ERROR: mismatched types
}
}

10 changes: 7 additions & 3 deletions src/test/ui/const-generics/issues/issue-62504.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
error: array lengths can't depend on generic parameters
--> $DIR/issue-62504.rs:18:25
error[E0308]: mismatched types
--> $DIR/issue-62504.rs:18:21
|
LL | ArrayHolder([0; Self::SIZE])
| ^^^^^^^^^^
| ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
|
= note: expected array `[u32; _]`
found array `[u32; _]`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
3 changes: 2 additions & 1 deletion src/test/ui/const-generics/issues/issue-67739.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Regression test for #67739

// check-pass

#![allow(incomplete_features)]
#![feature(const_generics)]

@@ -10,7 +12,6 @@ pub trait Trait {

fn associated_size(&self) -> usize {
[0u8; mem::size_of::<Self::Associated>()];
//~^ ERROR: array lengths can't depend on generic parameters
0
}
}
8 changes: 0 additions & 8 deletions src/test/ui/const-generics/issues/issue-67739.stderr

This file was deleted.

1 change: 1 addition & 0 deletions src/test/ui/consts/const-eval/const-eval-overflow-3.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ const A_I8_I
: [u32; (i8::MAX as usize) + 1]
= [0; (i8::MAX + 1) as usize];
//~^ ERROR evaluation of constant value failed
//~| ERROR mismatched types

fn main() {
foo(&A_I8_I[..]);
14 changes: 12 additions & 2 deletions src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
Original file line number Diff line number Diff line change
@@ -4,6 +4,16 @@ error[E0080]: evaluation of constant value failed
LL | = [0; (i8::MAX + 1) as usize];
| ^^^^^^^^^^^^^ attempt to add with overflow

error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/const-eval-overflow-3.rs:20:7
|
LL | = [0; (i8::MAX + 1) as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1) as usize`
|
= note: expected array `[u32; 128]`
found array `[u32; _]`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0080`.
Some errors have detailed explanations: E0080, E0308.
For more information about an error, try `rustc --explain E0080`.
1 change: 1 addition & 0 deletions src/test/ui/consts/const-eval/const-eval-overflow-3b.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ const A_I8_I
= [0; (i8::MAX + 1u8) as usize];
//~^ ERROR mismatched types
//~| ERROR cannot add `u8` to `i8`
//~| ERROR mismatched types

fn main() {
foo(&A_I8_I[..]);
11 changes: 10 additions & 1 deletion src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
Original file line number Diff line number Diff line change
@@ -12,7 +12,16 @@ LL | = [0; (i8::MAX + 1u8) as usize];
|
= help: the trait `std::ops::Add<u8>` is not implemented for `i8`

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/const-eval-overflow-3b.rs:18:7
|
LL | = [0; (i8::MAX + 1u8) as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1u8) as usize`
|
= note: expected array `[u32; 128]`
found array `[u32; _]`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
4 changes: 1 addition & 3 deletions src/test/ui/consts/const-eval/issue-52442.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
fn main() {
[(); { &loop { break } as *const _ as usize } ];
//~^ ERROR casting pointers to integers in constants is unstable
//~| ERROR `loop` is not allowed in a `const`
//~| ERROR evaluation of constant value failed
//~^ ERROR `loop` is not allowed in a `const`
}
20 changes: 2 additions & 18 deletions src/test/ui/consts/const-eval/issue-52442.stderr
Original file line number Diff line number Diff line change
@@ -7,22 +7,6 @@ LL | [(); { &loop { break } as *const _ as usize } ];
= note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information
= help: add `#![feature(const_loop)]` to the crate attributes to enable

error[E0658]: casting pointers to integers in constants is unstable
--> $DIR/issue-52442.rs:2:13
|
LL | [(); { &loop { break } as *const _ as usize } ];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable

error[E0080]: evaluation of constant value failed
--> $DIR/issue-52442.rs:2:13
|
LL | [(); { &loop { break } as *const _ as usize } ];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants

error: aborting due to 3 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0080, E0658.
For more information about an error, try `rustc --explain E0080`.
For more information about this error, try `rustc --explain E0658`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/match-test-ptr-null.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ fn main() {
// Make sure match uses the usual pointer comparison code path -- i.e., it should complain
// that pointer comparison is disallowed, not that parts of a pointer are accessed as raw
// bytes.
let _: [u8; 0] = [4; {
let _: [u8; 0] = [4; { //~ ERROR mismatched types
match &1 as *const i32 as usize {
//~^ ERROR casting pointers to integers in constants
//~| ERROR `match` is not allowed in a `const`
27 changes: 25 additions & 2 deletions src/test/ui/consts/const-eval/match-test-ptr-null.stderr
Original file line number Diff line number Diff line change
@@ -28,7 +28,30 @@ error[E0080]: evaluation of constant value failed
LL | match &1 as *const i32 as usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants

error: aborting due to 3 previous errors
error[E0308]: mismatched types
--> $DIR/match-test-ptr-null.rs:5:22
|
LL | let _: [u8; 0] = [4; {
| ____________-------___^
| | |
| | expected due to this
LL | | match &1 as *const i32 as usize {
LL | |
LL | |
... |
LL | | }
LL | | }];
| |______^ expected `0usize`, found `{
match &1 as *const i32 as usize {
0 => 42,
n => n,
}
}`
|
= note: expected array `[u8; 0]`
found array `[u8; _]`

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0080, E0658.
Some errors have detailed explanations: E0080, E0308, E0658.
For more information about an error, try `rustc --explain E0080`.
1 change: 0 additions & 1 deletion src/test/ui/consts/issue-52432.rs
Original file line number Diff line number Diff line change
@@ -6,5 +6,4 @@ fn main() {
//~| ERROR: type annotations needed
[(); &(static || {}) as *const _ as usize];
//~^ ERROR: closures cannot be static
//~| ERROR: evaluation of constant value failed
}
12 changes: 3 additions & 9 deletions src/test/ui/consts/issue-52432.stderr
Original file line number Diff line number Diff line change
@@ -16,13 +16,7 @@ error[E0282]: type annotations needed
LL | [(); &(static |x| {}) as *const _ as usize];
| ^ consider giving this closure parameter a type

error[E0080]: evaluation of constant value failed
--> $DIR/issue-52432.rs:7:10
|
LL | [(); &(static || {}) as *const _ as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0080, E0282, E0697.
For more information about an error, try `rustc --explain E0080`.
Some errors have detailed explanations: E0282, E0697.
For more information about an error, try `rustc --explain E0282`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
// we call the query `lit_to_const(input);`.
// However, the literal `input.lit` would not be of the type expected by `input.ty`.
// As a result, we immediately called `bug!(...)` instead of bubbling up the problem
// so that it could be handled by the caller of `lit_to_const` (`ast_const_to_const`).
// so that it could be handled by the caller of `lit_to_const` (`from_anon_const`).

fn main() {}

1 change: 1 addition & 0 deletions src/test/ui/consts/too_generic_eval_ice.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ impl<A, B> Foo<A, B> {
[5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE`
//~^ the size for values of type `A` cannot be known
//~| the size for values of type `B` cannot be known
//~| binary operation `==` cannot be applied to type `[{integer}; _]`
}
}

12 changes: 10 additions & 2 deletions src/test/ui/consts/too_generic_eval_ice.stderr
Original file line number Diff line number Diff line change
@@ -41,7 +41,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0]
= help: the trait `std::marker::Sized` is not implemented for `B`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error: aborting due to 3 previous errors
error[E0369]: binary operation `==` cannot be applied to type `[{integer}; _]`
--> $DIR/too_generic_eval_ice.rs:7:30
|
LL | [5; Self::HOST_SIZE] == [6; 0]
| -------------------- ^^ ------ [{integer}; 0]
| |
| [{integer}; _]

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0277, E0599.
Some errors have detailed explanations: E0277, E0369, E0599.
For more information about an error, try `rustc --explain E0277`.
1 change: 1 addition & 0 deletions src/test/ui/issues/issue-39559-2.rs
Original file line number Diff line number Diff line change
@@ -17,4 +17,5 @@ fn main() {
= [0; Dim3::dim()];
//~^ ERROR E0015
//~| ERROR E0080
//~| ERROR mismatched types
}
16 changes: 14 additions & 2 deletions src/test/ui/issues/issue-39559-2.stderr
Original file line number Diff line number Diff line change
@@ -22,7 +22,19 @@ error[E0080]: evaluation of constant value failed
LL | = [0; Dim3::dim()];
| ^^^^^^^^^^^ calling non-const function `<Dim3 as Dim>::dim`

error: aborting due to 4 previous errors
error[E0308]: mismatched types
--> $DIR/issue-39559-2.rs:17:11
|
LL | let array: [usize; Dim3::dim()]
| -------------------- expected due to this
...
LL | = [0; Dim3::dim()];
| ^^^^^^^^^^^^^^^^ expected `Dim3::dim()`, found `Dim3::dim()`
|
= note: expected array `[usize; _]`
found array `[usize; _]`

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0015, E0080.
Some errors have detailed explanations: E0015, E0080, E0308.
For more information about an error, try `rustc --explain E0015`.
1 change: 1 addition & 0 deletions src/test/ui/issues/issue-52060.rs
Original file line number Diff line number Diff line change
@@ -4,5 +4,6 @@ static A: &'static [u32] = &[1];
static B: [u32; 1] = [0; A.len()];
//~^ ERROR [E0013]
//~| ERROR evaluation of constant value failed
//~| ERROR mismatched types

fn main() {}
13 changes: 11 additions & 2 deletions src/test/ui/issues/issue-52060.stderr
Original file line number Diff line number Diff line change
@@ -12,7 +12,16 @@ error[E0080]: evaluation of constant value failed
LL | static B: [u32; 1] = [0; A.len()];
| ^ constant accesses static

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/issue-52060.rs:4:22
|
LL | static B: [u32; 1] = [0; A.len()];
| ^^^^^^^^^^^^ expected `1usize`, found `A.len()`
|
= note: expected array `[u32; 1]`
found array `[u32; _]`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0013, E0080.
Some errors have detailed explanations: E0013, E0080, E0308.
For more information about an error, try `rustc --explain E0013`.
Original file line number Diff line number Diff line change
@@ -19,5 +19,4 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`

fn main() {
let _ = [0; B::VALUE];
//~^ ERROR array lengths can't depend on generic parameters
}
Original file line number Diff line number Diff line change
@@ -13,13 +13,7 @@ LL | type MyA: TraitA;
LL | impl TraitB for B {
| ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation

error: array lengths can't depend on generic parameters
--> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
|
LL | let _ = [0; B::VALUE];
| ^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0046, E0437.
For more information about an error, try `rustc --explain E0046`.
12 changes: 6 additions & 6 deletions src/test/ui/repeat_count.stderr
Original file line number Diff line number Diff line change
@@ -28,6 +28,12 @@ error[E0308]: mismatched types
LL | let e = [0; "foo"];
| ^^^^^ expected `usize`, found `&str`

error[E0308]: mismatched types
--> $DIR/repeat_count.rs:28:17
|
LL | let g = [0; G { g: () }];
| ^^^^^^^^^^^ expected `usize`, found struct `main::G`

error[E0308]: mismatched types
--> $DIR/repeat_count.rs:19:17
|
@@ -50,12 +56,6 @@ help: you can convert an `isize` to `usize` and panic if the converted value wou
LL | let f = [0_usize; (-1_isize).try_into().unwrap()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
--> $DIR/repeat_count.rs:28:17
|
LL | let g = [0; G { g: () }];
| ^^^^^^^^^^^ expected `usize`, found struct `main::G`

error: aborting due to 8 previous errors

Some errors have detailed explanations: E0308, E0435.
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ fn i<const N: usize>() {
static a: [u8; N] = [0; N];
//~^ ERROR can't use generic parameters from outer function
//~^^ ERROR can't use generic parameters from outer function
//~| ERROR mismatched types
}

fn main() {}
14 changes: 12 additions & 2 deletions src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr
Original file line number Diff line number Diff line change
@@ -48,6 +48,16 @@ LL | #![feature(const_generics)]
|
= note: `#[warn(incomplete_features)]` on by default

error: aborting due to 5 previous errors
error[E0308]: mismatched types
--> $DIR/issue-65035-static-with-parent-generics.rs:24:25
|
LL | static a: [u8; N] = [0; N];
| ^^^^^^ expected `N`, found `N`
|
= note: expected array `[u8; _]`
found array `[u8; _]`

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0401`.
Some errors have detailed explanations: E0308, E0401.
For more information about an error, try `rustc --explain E0308`.