mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-07 04:23:30 +00:00
Auto merge of #92560 - matthiaskrgr:rollup-jeli7ip, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #91587 (core::ops::unsize: improve docs for DispatchFromDyn) - #91907 (Allow `_` as the length of array types and repeat expressions) - #92515 (RustWrapper: adapt for an LLVM API change) - #92516 (Do not use deprecated -Zsymbol-mangling-version in bootstrap) - #92530 (Move `contains` method of Option and Result lower in docs) - #92546 (Update books) - #92551 (rename StackPopClean::None to Root) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5883b87563
@ -34,7 +34,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
ExprKind::Repeat(ref expr, ref count) => {
|
ExprKind::Repeat(ref expr, ref count) => {
|
||||||
let expr = self.lower_expr(expr);
|
let expr = self.lower_expr(expr);
|
||||||
let count = self.lower_anon_const(count);
|
let count = self.lower_array_length(count);
|
||||||
hir::ExprKind::Repeat(expr, count)
|
hir::ExprKind::Repeat(expr, count)
|
||||||
}
|
}
|
||||||
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
||||||
|
@ -56,6 +56,7 @@ use rustc_hir::{ConstArg, GenericArg, ParamName};
|
|||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_session::lint::LintBuffer;
|
use rustc_session::lint::LintBuffer;
|
||||||
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
|
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::hygiene::ExpnId;
|
use rustc_span::hygiene::ExpnId;
|
||||||
@ -1248,7 +1249,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length))
|
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
||||||
}
|
}
|
||||||
TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
||||||
TyKind::TraitObject(ref bounds, kind) => {
|
TyKind::TraitObject(ref bounds, kind) => {
|
||||||
@ -2039,6 +2040,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
self.expr_block(block, AttrVec::new())
|
self.expr_block(block, AttrVec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
|
||||||
|
match c.value.kind {
|
||||||
|
ExprKind::Underscore => {
|
||||||
|
if self.sess.features_untracked().generic_arg_infer {
|
||||||
|
hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span)
|
||||||
|
} else {
|
||||||
|
feature_err(
|
||||||
|
&self.sess.parse_sess,
|
||||||
|
sym::generic_arg_infer,
|
||||||
|
c.value.span,
|
||||||
|
"using `_` for array lengths is unstable",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
hir::ArrayLen::Body(self.lower_anon_const(c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
|
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
|
||||||
self.with_new_scopes(|this| hir::AnonConst {
|
self.with_new_scopes(|this| hir::AnonConst {
|
||||||
hir_id: this.lower_node_id(c.id),
|
hir_id: this.lower_node_id(c.id),
|
||||||
|
@ -160,17 +160,17 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
|
|||||||
// the values should match the ones in the DWARF standard anyway.
|
// the values should match the ones in the DWARF standard anyway.
|
||||||
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
|
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
|
||||||
let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
|
let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
|
||||||
let mut addr_ops = SmallVec::<[_; 8]>::new();
|
let mut addr_ops = SmallVec::<[u64; 8]>::new();
|
||||||
|
|
||||||
if direct_offset.bytes() > 0 {
|
if direct_offset.bytes() > 0 {
|
||||||
addr_ops.push(op_plus_uconst());
|
addr_ops.push(op_plus_uconst());
|
||||||
addr_ops.push(direct_offset.bytes() as i64);
|
addr_ops.push(direct_offset.bytes() as u64);
|
||||||
}
|
}
|
||||||
for &offset in indirect_offsets {
|
for &offset in indirect_offsets {
|
||||||
addr_ops.push(op_deref());
|
addr_ops.push(op_deref());
|
||||||
if offset.bytes() > 0 {
|
if offset.bytes() > 0 {
|
||||||
addr_ops.push(op_plus_uconst());
|
addr_ops.push(op_plus_uconst());
|
||||||
addr_ops.push(offset.bytes() as i64);
|
addr_ops.push(offset.bytes() as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2108,7 +2108,7 @@ extern "C" {
|
|||||||
Builder: &DIBuilder<'a>,
|
Builder: &DIBuilder<'a>,
|
||||||
Val: &'a Value,
|
Val: &'a Value,
|
||||||
VarInfo: &'a DIVariable,
|
VarInfo: &'a DIVariable,
|
||||||
AddrOps: *const i64,
|
AddrOps: *const u64,
|
||||||
AddrOpsCount: c_uint,
|
AddrOpsCount: c_uint,
|
||||||
DL: &'a DILocation,
|
DL: &'a DILocation,
|
||||||
InsertAtEnd: &'a BasicBlock,
|
InsertAtEnd: &'a BasicBlock,
|
||||||
@ -2199,8 +2199,8 @@ extern "C" {
|
|||||||
Scope: &'a DIScope,
|
Scope: &'a DIScope,
|
||||||
InlinedAt: Option<&'a DILocation>,
|
InlinedAt: Option<&'a DILocation>,
|
||||||
) -> &'a DILocation;
|
) -> &'a DILocation;
|
||||||
pub fn LLVMRustDIBuilderCreateOpDeref() -> i64;
|
pub fn LLVMRustDIBuilderCreateOpDeref() -> u64;
|
||||||
pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64;
|
pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64;
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
|
pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
|
||||||
|
@ -63,7 +63,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
|||||||
cid.instance,
|
cid.instance,
|
||||||
body,
|
body,
|
||||||
Some(&ret.into()),
|
Some(&ret.into()),
|
||||||
StackPopCleanup::None { cleanup: false },
|
StackPopCleanup::Root { cleanup: false },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// The main interpreter loop.
|
// The main interpreter loop.
|
||||||
|
@ -156,11 +156,11 @@ pub enum StackPopCleanup {
|
|||||||
/// `ret` stores the block we jump to on a normal return, while `unwind`
|
/// `ret` stores the block we jump to on a normal return, while `unwind`
|
||||||
/// stores the block used for cleanup during unwinding.
|
/// stores the block used for cleanup during unwinding.
|
||||||
Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
|
Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
|
||||||
/// Just do nothing: Used by Main and for TLS hooks in miri.
|
/// The root frame of the stack: nowhere else to jump to.
|
||||||
/// `cleanup` says whether locals are deallocated. Static computation
|
/// `cleanup` says whether locals are deallocated. Static computation
|
||||||
/// wants them leaked to intern what they need (and just throw away
|
/// wants them leaked to intern what they need (and just throw away
|
||||||
/// the entire `ecx` when it is done).
|
/// the entire `ecx` when it is done).
|
||||||
None { cleanup: bool },
|
Root { cleanup: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State of a local variable including a memoized layout
|
/// State of a local variable including a memoized layout
|
||||||
@ -849,7 +849,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// because this is CTFE and the final value will be thoroughly validated anyway.
|
// because this is CTFE and the final value will be thoroughly validated anyway.
|
||||||
let cleanup = match return_to_block {
|
let cleanup = match return_to_block {
|
||||||
StackPopCleanup::Goto { .. } => true,
|
StackPopCleanup::Goto { .. } => true,
|
||||||
StackPopCleanup::None { cleanup, .. } => cleanup,
|
StackPopCleanup::Root { cleanup, .. } => cleanup,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !cleanup {
|
if !cleanup {
|
||||||
@ -874,8 +874,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// Follow the unwind edge.
|
// Follow the unwind edge.
|
||||||
let unwind = match return_to_block {
|
let unwind = match return_to_block {
|
||||||
StackPopCleanup::Goto { unwind, .. } => unwind,
|
StackPopCleanup::Goto { unwind, .. } => unwind,
|
||||||
StackPopCleanup::None { .. } => {
|
StackPopCleanup::Root { .. } => {
|
||||||
panic!("Encountered StackPopCleanup::None when unwinding!")
|
panic!("encountered StackPopCleanup::Root when unwinding!")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.unwind_to_block(unwind)
|
self.unwind_to_block(unwind)
|
||||||
@ -883,7 +883,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// Follow the normal return edge.
|
// Follow the normal return edge.
|
||||||
match return_to_block {
|
match return_to_block {
|
||||||
StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
|
StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
|
||||||
StackPopCleanup::None { .. } => Ok(()),
|
StackPopCleanup::Root { .. } => {
|
||||||
|
assert!(
|
||||||
|
self.stack().is_empty(),
|
||||||
|
"only the topmost frame can have StackPopCleanup::Root"
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1407,6 +1407,20 @@ impl fmt::Display for ConstContext {
|
|||||||
/// A literal.
|
/// A literal.
|
||||||
pub type Lit = Spanned<LitKind>;
|
pub type Lit = Spanned<LitKind>;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
|
||||||
|
pub enum ArrayLen {
|
||||||
|
Infer(HirId, Span),
|
||||||
|
Body(AnonConst),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArrayLen {
|
||||||
|
pub fn hir_id(&self) -> HirId {
|
||||||
|
match self {
|
||||||
|
&ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A constant (expression) that's not an item or associated item,
|
/// A constant (expression) that's not an item or associated item,
|
||||||
/// but needs its own `DefId` for type-checking, const-eval, etc.
|
/// but needs its own `DefId` for type-checking, const-eval, etc.
|
||||||
/// These are usually found nested inside types (e.g., array lengths)
|
/// These are usually found nested inside types (e.g., array lengths)
|
||||||
@ -1756,7 +1770,7 @@ pub enum ExprKind<'hir> {
|
|||||||
///
|
///
|
||||||
/// E.g., `[1; 5]`. The first expression is the element
|
/// E.g., `[1; 5]`. The first expression is the element
|
||||||
/// to be repeated; the second is the number of times to repeat it.
|
/// to be repeated; the second is the number of times to repeat it.
|
||||||
Repeat(&'hir Expr<'hir>, AnonConst),
|
Repeat(&'hir Expr<'hir>, ArrayLen),
|
||||||
|
|
||||||
/// A suspension point for generators (i.e., `yield <expr>`).
|
/// A suspension point for generators (i.e., `yield <expr>`).
|
||||||
Yield(&'hir Expr<'hir>, YieldSource),
|
Yield(&'hir Expr<'hir>, YieldSource),
|
||||||
@ -2266,7 +2280,7 @@ pub enum TyKind<'hir> {
|
|||||||
/// A variable length slice (i.e., `[T]`).
|
/// A variable length slice (i.e., `[T]`).
|
||||||
Slice(&'hir Ty<'hir>),
|
Slice(&'hir Ty<'hir>),
|
||||||
/// A fixed length array (i.e., `[T; n]`).
|
/// A fixed length array (i.e., `[T; n]`).
|
||||||
Array(&'hir Ty<'hir>, AnonConst),
|
Array(&'hir Ty<'hir>, ArrayLen),
|
||||||
/// A raw pointer (i.e., `*const T` or `*mut T`).
|
/// A raw pointer (i.e., `*const T` or `*mut T`).
|
||||||
Ptr(MutTy<'hir>),
|
Ptr(MutTy<'hir>),
|
||||||
/// A reference (i.e., `&'a T` or `&'a mut T`).
|
/// A reference (i.e., `&'a T` or `&'a mut T`).
|
||||||
|
@ -383,6 +383,9 @@ pub trait Visitor<'v>: Sized {
|
|||||||
fn visit_pat(&mut self, p: &'v Pat<'v>) {
|
fn visit_pat(&mut self, p: &'v Pat<'v>) {
|
||||||
walk_pat(self, p)
|
walk_pat(self, p)
|
||||||
}
|
}
|
||||||
|
fn visit_array_length(&mut self, len: &'v ArrayLen) {
|
||||||
|
walk_array_len(self, len)
|
||||||
|
}
|
||||||
fn visit_anon_const(&mut self, c: &'v AnonConst) {
|
fn visit_anon_const(&mut self, c: &'v AnonConst) {
|
||||||
walk_anon_const(self, c)
|
walk_anon_const(self, c)
|
||||||
}
|
}
|
||||||
@ -753,7 +756,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
|
|||||||
}
|
}
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visitor.visit_anon_const(length)
|
visitor.visit_array_length(length)
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
|
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
|
||||||
for bound in bounds {
|
for bound in bounds {
|
||||||
@ -1124,6 +1127,13 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
|
||||||
|
match len {
|
||||||
|
&ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id),
|
||||||
|
ArrayLen::Body(c) => visitor.visit_anon_const(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
|
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
|
||||||
visitor.visit_id(constant.hir_id);
|
visitor.visit_id(constant.hir_id);
|
||||||
visitor.visit_nested_body(constant.body);
|
visitor.visit_nested_body(constant.body);
|
||||||
@ -1147,7 +1157,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||||||
ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
|
ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
|
||||||
ExprKind::Repeat(ref element, ref count) => {
|
ExprKind::Repeat(ref element, ref count) => {
|
||||||
visitor.visit_expr(element);
|
visitor.visit_expr(element);
|
||||||
visitor.visit_anon_const(count)
|
visitor.visit_array_length(count)
|
||||||
}
|
}
|
||||||
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
|
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
|
||||||
visitor.visit_qpath(qpath, expression.hir_id, expression.span);
|
visitor.visit_qpath(qpath, expression.hir_id, expression.span);
|
||||||
|
@ -358,7 +358,7 @@ impl<'a> State<'a> {
|
|||||||
self.word("[");
|
self.word("[");
|
||||||
self.print_type(&ty);
|
self.print_type(&ty);
|
||||||
self.word("; ");
|
self.word("; ");
|
||||||
self.print_anon_const(length);
|
self.print_array_length(length);
|
||||||
self.word("]");
|
self.word("]");
|
||||||
}
|
}
|
||||||
hir::TyKind::Typeof(ref e) => {
|
hir::TyKind::Typeof(ref e) => {
|
||||||
@ -1065,6 +1065,13 @@ impl<'a> State<'a> {
|
|||||||
self.print_else(elseopt)
|
self.print_else(elseopt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_array_length(&mut self, len: &hir::ArrayLen) {
|
||||||
|
match len {
|
||||||
|
hir::ArrayLen::Infer(_, _) => self.word("_"),
|
||||||
|
hir::ArrayLen::Body(ct) => self.print_anon_const(ct),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
|
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
|
||||||
self.ann.nested(self, Nested::Body(constant.body))
|
self.ann.nested(self, Nested::Body(constant.body))
|
||||||
}
|
}
|
||||||
@ -1140,12 +1147,12 @@ impl<'a> State<'a> {
|
|||||||
self.end()
|
self.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) {
|
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) {
|
||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
self.print_expr(element);
|
self.print_expr(element);
|
||||||
self.word_space(";");
|
self.word_space(";");
|
||||||
self.print_anon_const(count);
|
self.print_array_length(count);
|
||||||
self.word("]");
|
self.word("]");
|
||||||
self.end()
|
self.end()
|
||||||
}
|
}
|
||||||
|
@ -979,11 +979,11 @@ LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
|
|||||||
|
|
||||||
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
||||||
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
|
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
|
||||||
int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
|
uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
|
||||||
LLVMBasicBlockRef InsertAtEnd) {
|
LLVMBasicBlockRef InsertAtEnd) {
|
||||||
return wrap(Builder->insertDeclare(
|
return wrap(Builder->insertDeclare(
|
||||||
unwrap(V), unwrap<DILocalVariable>(VarInfo),
|
unwrap(V), unwrap<DILocalVariable>(VarInfo),
|
||||||
Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
|
Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
|
||||||
DebugLoc(cast<MDNode>(unwrap(DL))),
|
DebugLoc(cast<MDNode>(unwrap(DL))),
|
||||||
unwrap(InsertAtEnd)));
|
unwrap(InsertAtEnd)));
|
||||||
}
|
}
|
||||||
@ -1057,11 +1057,11 @@ LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
|
|||||||
return wrap(Loc);
|
return wrap(Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
|
extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
|
||||||
return dwarf::DW_OP_deref;
|
return dwarf::DW_OP_deref;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
|
extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
|
||||||
return dwarf::DW_OP_plus_uconst;
|
return dwarf::DW_OP_plus_uconst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,9 +583,12 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
ExprKind::ConstBlock { value }
|
ExprKind::ConstBlock { value }
|
||||||
}
|
}
|
||||||
// Now comes the rote stuff:
|
// Now comes the rote stuff:
|
||||||
hir::ExprKind::Repeat(ref v, ref count) => {
|
hir::ExprKind::Repeat(ref v, _) => {
|
||||||
let count_def_id = self.tcx.hir().local_def_id(count.hir_id);
|
let ty = self.typeck_results().expr_ty(expr);
|
||||||
let count = ty::Const::from_anon_const(self.tcx, count_def_id);
|
let count = match ty.kind() {
|
||||||
|
ty::Array(_, ct) => ct,
|
||||||
|
_ => span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty),
|
||||||
|
};
|
||||||
|
|
||||||
ExprKind::Repeat { value: self.mirror_expr(v), count }
|
ExprKind::Repeat { value: self.mirror_expr(v), count }
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||||||
Instance::new(def_id, substs),
|
Instance::new(def_id, substs),
|
||||||
dummy_body,
|
dummy_body,
|
||||||
ret.as_ref(),
|
ret.as_ref(),
|
||||||
StackPopCleanup::None { cleanup: false },
|
StackPopCleanup::Root { cleanup: false },
|
||||||
)
|
)
|
||||||
.expect("failed to push initial stack frame");
|
.expect("failed to push initial stack frame");
|
||||||
|
|
||||||
|
@ -1326,12 +1326,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
|||||||
}
|
}
|
||||||
intravisit::walk_qpath(self, path, t.hir_id, t.span);
|
intravisit::walk_qpath(self, path, t.hir_id, t.span);
|
||||||
}
|
}
|
||||||
hir::TyKind::Array(ref ty, ref anon_const) => {
|
hir::TyKind::Array(ref ty, ref length) => {
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
let map = self.tcx.hir();
|
let map = self.tcx.hir();
|
||||||
self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
match length {
|
||||||
v.visit_expr(&map.body(anon_const.body).value)
|
// FIXME(generic_arg_infer): We probably want to
|
||||||
});
|
// output the inferred type here? :shrug:
|
||||||
|
hir::ArrayLen::Infer(..) => {}
|
||||||
|
hir::ArrayLen::Body(anon_const) => self
|
||||||
|
.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||||
|
v.visit_expr(&map.body(anon_const.body).value)
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hir::TyKind::OpaqueDef(item_id, _) => {
|
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||||
let item = self.tcx.hir().item(item_id);
|
let item = self.tcx.hir().item(item_id);
|
||||||
@ -1390,12 +1396,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
|
|||||||
v.visit_expr(&body.value)
|
v.visit_expr(&body.value)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
hir::ExprKind::Repeat(ref expr, ref anon_const) => {
|
hir::ExprKind::Repeat(ref expr, ref length) => {
|
||||||
self.visit_expr(expr);
|
self.visit_expr(expr);
|
||||||
let map = self.tcx.hir();
|
let map = self.tcx.hir();
|
||||||
self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
match length {
|
||||||
v.visit_expr(&map.body(anon_const.body).value)
|
// FIXME(generic_arg_infer): We probably want to
|
||||||
});
|
// output the inferred type here? :shrug:
|
||||||
|
hir::ArrayLen::Infer(..) => {}
|
||||||
|
hir::ArrayLen::Body(anon_const) => self
|
||||||
|
.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
|
||||||
|
v.visit_expr(&map.body(anon_const.body).value)
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// In particular, we take this branch for call and path expressions,
|
// In particular, we take this branch for call and path expressions,
|
||||||
// where we'll index the idents involved just by continuing to walk.
|
// where we'll index the idents involved just by continuing to walk.
|
||||||
|
@ -310,9 +310,9 @@ impl<'hir> Sig for hir::Ty<'hir> {
|
|||||||
let nested = bounds_to_string(&bounds);
|
let nested = bounds_to_string(&bounds);
|
||||||
Ok(text_sig(nested))
|
Ok(text_sig(nested))
|
||||||
}
|
}
|
||||||
hir::TyKind::Array(ref ty, ref anon_const) => {
|
hir::TyKind::Array(ref ty, ref length) => {
|
||||||
let nested_ty = ty.make(offset + 1, id, scx)?;
|
let nested_ty = ty.make(offset + 1, id, scx)?;
|
||||||
let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " ");
|
let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " ");
|
||||||
let text = format!("[{}; {}]", nested_ty.text, expr);
|
let text = format!("[{}; {}]", nested_ty.text, expr);
|
||||||
Ok(replace_text(nested_ty, text))
|
Ok(replace_text(nested_ty, text))
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
|
||||||
GenericParamDefKind::Const { .. },
|
GenericParamDefKind::Const { .. },
|
||||||
) if tcx.type_of(param.def_id) == tcx.types.usize => {
|
) if tcx.type_of(param.def_id) == tcx.types.usize => {
|
||||||
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
|
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
|
||||||
if let Ok(snippet) = snippet {
|
if let Ok(snippet) = snippet {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
arg.span(),
|
arg.span(),
|
||||||
|
@ -2363,8 +2363,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
|
self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
|
||||||
}
|
}
|
||||||
hir::TyKind::Array(ref ty, ref length) => {
|
hir::TyKind::Array(ref ty, ref length) => {
|
||||||
let length_def_id = tcx.hir().local_def_id(length.hir_id);
|
let length = match length {
|
||||||
let length = ty::Const::from_anon_const(tcx, length_def_id);
|
&hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span),
|
||||||
|
hir::ArrayLen::Body(constant) => {
|
||||||
|
let length_def_id = tcx.hir().local_def_id(constant.hir_id);
|
||||||
|
ty::Const::from_anon_const(tcx, length_def_id)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length));
|
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length));
|
||||||
self.normalize_ty(ast_ty.span, array_ty)
|
self.normalize_ty(ast_ty.span, array_ty)
|
||||||
}
|
}
|
||||||
|
@ -1238,12 +1238,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
fn check_expr_repeat(
|
fn check_expr_repeat(
|
||||||
&self,
|
&self,
|
||||||
element: &'tcx hir::Expr<'tcx>,
|
element: &'tcx hir::Expr<'tcx>,
|
||||||
count: &'tcx hir::AnonConst,
|
count: &'tcx hir::ArrayLen,
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
_expr: &'tcx hir::Expr<'tcx>,
|
_expr: &'tcx hir::Expr<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let count = self.to_const(count);
|
let count = self.array_length_to_const(count);
|
||||||
|
|
||||||
let uty = match expected {
|
let uty = match expected {
|
||||||
ExpectHasType(uty) => match *uty.kind() {
|
ExpectHasType(uty) => match *uty.kind() {
|
||||||
|
@ -498,6 +498,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> &'tcx ty::Const<'tcx> {
|
||||||
|
match length {
|
||||||
|
&hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span),
|
||||||
|
hir::ArrayLen::Body(anon_const) => self.to_const(anon_const),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
|
pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
|
||||||
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
||||||
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
||||||
|
@ -182,7 +182,7 @@ crate fn placeholder_type_error<'tcx>(
|
|||||||
sugg.push((span, format!(", {}", type_name)));
|
sugg.push((span, format!(", {}", type_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut err = bad_placeholder_type(tcx, placeholder_types, kind);
|
let mut err = bad_placeholder(tcx, "type", placeholder_types, kind);
|
||||||
|
|
||||||
// Suggest, but only if it is not a function in const or static
|
// Suggest, but only if it is not a function in const or static
|
||||||
if suggest {
|
if suggest {
|
||||||
@ -314,8 +314,9 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Utility types and common code for the above passes.
|
// Utility types and common code for the above passes.
|
||||||
|
|
||||||
fn bad_placeholder_type<'tcx>(
|
fn bad_placeholder<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
placeholder_kind: &'static str,
|
||||||
mut spans: Vec<Span>,
|
mut spans: Vec<Span>,
|
||||||
kind: &'static str,
|
kind: &'static str,
|
||||||
) -> rustc_errors::DiagnosticBuilder<'tcx> {
|
) -> rustc_errors::DiagnosticBuilder<'tcx> {
|
||||||
@ -326,7 +327,8 @@ fn bad_placeholder_type<'tcx>(
|
|||||||
tcx.sess,
|
tcx.sess,
|
||||||
spans.clone(),
|
spans.clone(),
|
||||||
E0121,
|
E0121,
|
||||||
"the type placeholder `_` is not allowed within types on item signatures for {}",
|
"the {} placeholder `_` is not allowed within types on item signatures for {}",
|
||||||
|
placeholder_kind,
|
||||||
kind
|
kind
|
||||||
);
|
);
|
||||||
for span in spans {
|
for span in spans {
|
||||||
@ -393,7 +395,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||||||
_: Option<&ty::GenericParamDef>,
|
_: Option<&ty::GenericParamDef>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> &'tcx Const<'tcx> {
|
) -> &'tcx Const<'tcx> {
|
||||||
bad_placeholder_type(self.tcx(), vec![span], "generic").emit();
|
bad_placeholder(self.tcx(), "const", vec![span], "generic").emit();
|
||||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||||
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
|
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
|
||||||
ty::ReErased => self.tcx.lifetimes.re_static,
|
ty::ReErased => self.tcx.lifetimes.re_static,
|
||||||
@ -1482,7 +1484,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||||||
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
||||||
// as they shouldn't be able to cause query cycle errors.
|
// as they shouldn't be able to cause query cycle errors.
|
||||||
Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||||
| Node::Variant(Variant { disr_expr: Some(ref constant), .. })
|
if constant.hir_id() == hir_id =>
|
||||||
|
{
|
||||||
|
Some(parent_def_id.to_def_id())
|
||||||
|
}
|
||||||
|
Node::Variant(Variant { disr_expr: Some(ref constant), .. })
|
||||||
if constant.hir_id == hir_id =>
|
if constant.hir_id == hir_id =>
|
||||||
{
|
{
|
||||||
Some(parent_def_id.to_def_id())
|
Some(parent_def_id.to_def_id())
|
||||||
@ -1788,7 +1794,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
|||||||
|
|
||||||
let mut visitor = PlaceholderHirTyCollector::default();
|
let mut visitor = PlaceholderHirTyCollector::default();
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
|
let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type");
|
||||||
let ret_ty = fn_sig.skip_binder().output();
|
let ret_ty = fn_sig.skip_binder().output();
|
||||||
if !ret_ty.references_error() {
|
if !ret_ty.references_error() {
|
||||||
if !ret_ty.is_closure() {
|
if !ret_ty.is_closure() {
|
||||||
|
@ -13,7 +13,7 @@ use rustc_span::symbol::Ident;
|
|||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
use super::ItemCtxt;
|
use super::ItemCtxt;
|
||||||
use super::{bad_placeholder_type, is_suggestable_infer_ty};
|
use super::{bad_placeholder, is_suggestable_infer_ty};
|
||||||
|
|
||||||
/// Computes the relevant generic parameter for a potential generic const argument.
|
/// Computes the relevant generic parameter for a potential generic const argument.
|
||||||
///
|
///
|
||||||
@ -490,7 +490,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
|||||||
match parent_node {
|
match parent_node {
|
||||||
Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
|
Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||||
if constant.hir_id == hir_id =>
|
if constant.hir_id() == hir_id =>
|
||||||
{
|
{
|
||||||
tcx.types.usize
|
tcx.types.usize
|
||||||
}
|
}
|
||||||
@ -788,7 +788,7 @@ fn infer_placeholder_type<'a>(
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let mut diag = bad_placeholder_type(tcx, vec![span], kind);
|
let mut diag = bad_placeholder(tcx, "type", vec![span], kind);
|
||||||
|
|
||||||
if !ty.references_error() {
|
if !ty.references_error() {
|
||||||
let mut mk_nameable = MakeNameable::new(tcx);
|
let mut mk_nameable = MakeNameable::new(tcx);
|
||||||
|
@ -68,7 +68,38 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
|
|||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||||
|
|
||||||
/// This is used for object safety, to check that a method's receiver type can be dispatched on.
|
/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing
|
||||||
|
/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on.
|
||||||
|
///
|
||||||
|
/// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different
|
||||||
|
/// interpretation).
|
||||||
|
///
|
||||||
|
/// Imagine we have a trait object `t` with type `&dyn Tr`, where `Tr` is some trait with a method
|
||||||
|
/// `m` defined as `fn m(&self);`. When calling `t.m()`, the receiver `t` is a wide pointer, but an
|
||||||
|
/// implementation of `m` will expect a narrow pointer as `&self` (a reference to the concrete
|
||||||
|
/// type). The compiler must generate an implicit conversion from the trait object/wide pointer to
|
||||||
|
/// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that
|
||||||
|
/// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as
|
||||||
|
/// the self type in an object-safe method. (in the above example, the compiler will require
|
||||||
|
/// `DispatchFromDyn` is implemented for `&'a U`).
|
||||||
|
///
|
||||||
|
/// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the
|
||||||
|
/// conversion is hard-wired into the compiler. For the conversion to work, the following
|
||||||
|
/// properties must hold (i.e., it is only safe to implement `DispatchFromDyn` for types which have
|
||||||
|
/// these properties, these are also checked by the compiler):
|
||||||
|
///
|
||||||
|
/// * EITHER `Self` and `T` are either both references or both raw pointers; in either case, with
|
||||||
|
/// the same mutability.
|
||||||
|
/// * OR, all of the following hold
|
||||||
|
/// - `Self` and `T` must have the same type constructor, and only vary in a single type parameter
|
||||||
|
/// formal (the *coerced type*, e.g., `impl DispatchFromDyn<Rc<T>> for Rc<U>` is ok and the
|
||||||
|
/// single type parameter (instantiated with `T` or `U`) is the coerced type,
|
||||||
|
/// `impl DispatchFromDyn<Arc<T>> for Rc<U>` is not ok).
|
||||||
|
/// - The definition for `Self` must be a struct.
|
||||||
|
/// - The definition for `Self` must not be `#[repr(packed)]` or `#[repr(C)]`.
|
||||||
|
/// - Other than one-aligned, zero-sized fields, the definition for `Self` must have exactly one
|
||||||
|
/// field and that field's type must be the coerced type. Furthermore, `Self`'s field type must
|
||||||
|
/// implement `DispatchFromDyn<F>` where `F` is the type of `T`'s field type.
|
||||||
///
|
///
|
||||||
/// An example implementation of the trait:
|
/// An example implementation of the trait:
|
||||||
///
|
///
|
||||||
|
@ -571,36 +571,6 @@ impl<T> Option<T> {
|
|||||||
!self.is_some()
|
!self.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the option is a [`Some`] value containing the given value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(option_result_contains)]
|
|
||||||
///
|
|
||||||
/// let x: Option<u32> = Some(2);
|
|
||||||
/// assert_eq!(x.contains(&2), true);
|
|
||||||
///
|
|
||||||
/// let x: Option<u32> = Some(3);
|
|
||||||
/// assert_eq!(x.contains(&2), false);
|
|
||||||
///
|
|
||||||
/// let x: Option<u32> = None;
|
|
||||||
/// assert_eq!(x.contains(&2), false);
|
|
||||||
/// ```
|
|
||||||
#[must_use]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "option_result_contains", issue = "62358")]
|
|
||||||
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
|
|
||||||
pub const fn contains<U>(&self, x: &U) -> bool
|
|
||||||
where
|
|
||||||
U: ~const PartialEq<T>,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Some(y) => x.eq(y),
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Adapter for working with references
|
// Adapter for working with references
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
@ -1573,6 +1543,36 @@ impl<T> Option<T> {
|
|||||||
mem::replace(self, Some(value))
|
mem::replace(self, Some(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the option is a [`Some`] value containing the given value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(option_result_contains)]
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = Some(2);
|
||||||
|
/// assert_eq!(x.contains(&2), true);
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = Some(3);
|
||||||
|
/// assert_eq!(x.contains(&2), false);
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = None;
|
||||||
|
/// assert_eq!(x.contains(&2), false);
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "option_result_contains", issue = "62358")]
|
||||||
|
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
|
||||||
|
pub const fn contains<U>(&self, x: &U) -> bool
|
||||||
|
where
|
||||||
|
U: ~const PartialEq<T>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Some(y) => x.eq(y),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Zips `self` with another `Option`.
|
/// Zips `self` with another `Option`.
|
||||||
///
|
///
|
||||||
/// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`.
|
/// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`.
|
||||||
|
@ -563,64 +563,6 @@ impl<T, E> Result<T, E> {
|
|||||||
!self.is_ok()
|
!self.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the result is an [`Ok`] value containing the given value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(option_result_contains)]
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Ok(2);
|
|
||||||
/// assert_eq!(x.contains(&2), true);
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Ok(3);
|
|
||||||
/// assert_eq!(x.contains(&2), false);
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Err("Some error message");
|
|
||||||
/// assert_eq!(x.contains(&2), false);
|
|
||||||
/// ```
|
|
||||||
#[must_use]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "option_result_contains", issue = "62358")]
|
|
||||||
pub fn contains<U>(&self, x: &U) -> bool
|
|
||||||
where
|
|
||||||
U: PartialEq<T>,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Ok(y) => x == y,
|
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the result is an [`Err`] value containing the given value.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(result_contains_err)]
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Ok(2);
|
|
||||||
/// assert_eq!(x.contains_err(&"Some error message"), false);
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Err("Some error message");
|
|
||||||
/// assert_eq!(x.contains_err(&"Some error message"), true);
|
|
||||||
///
|
|
||||||
/// let x: Result<u32, &str> = Err("Some other error message");
|
|
||||||
/// assert_eq!(x.contains_err(&"Some error message"), false);
|
|
||||||
/// ```
|
|
||||||
#[must_use]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "result_contains_err", issue = "62358")]
|
|
||||||
pub fn contains_err<F>(&self, f: &F) -> bool
|
|
||||||
where
|
|
||||||
F: PartialEq<E>,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Ok(_) => false,
|
|
||||||
Err(e) => f == e,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Adapter for each variant
|
// Adapter for each variant
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
@ -1491,6 +1433,68 @@ impl<T, E> Result<T, E> {
|
|||||||
Err(e) => e,
|
Err(e) => e,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Misc or niche
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Returns `true` if the result is an [`Ok`] value containing the given value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(option_result_contains)]
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Ok(2);
|
||||||
|
/// assert_eq!(x.contains(&2), true);
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Ok(3);
|
||||||
|
/// assert_eq!(x.contains(&2), false);
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Err("Some error message");
|
||||||
|
/// assert_eq!(x.contains(&2), false);
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "option_result_contains", issue = "62358")]
|
||||||
|
pub fn contains<U>(&self, x: &U) -> bool
|
||||||
|
where
|
||||||
|
U: PartialEq<T>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Ok(y) => x == y,
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the result is an [`Err`] value containing the given value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(result_contains_err)]
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Ok(2);
|
||||||
|
/// assert_eq!(x.contains_err(&"Some error message"), false);
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Err("Some error message");
|
||||||
|
/// assert_eq!(x.contains_err(&"Some error message"), true);
|
||||||
|
///
|
||||||
|
/// let x: Result<u32, &str> = Err("Some other error message");
|
||||||
|
/// assert_eq!(x.contains_err(&"Some error message"), false);
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "result_contains_err", issue = "62358")]
|
||||||
|
pub fn contains_err<F>(&self, f: &F) -> bool
|
||||||
|
where
|
||||||
|
F: PartialEq<E>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Ok(_) => false,
|
||||||
|
Err(e) => f == e,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E> Result<&T, E> {
|
impl<T, E> Result<&T, E> {
|
||||||
|
@ -988,10 +988,20 @@ impl<'a> Builder<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if use_new_symbol_mangling {
|
// cfg(bootstrap) -- drop the compiler.stage == 0 branch.
|
||||||
rustflags.arg("-Zsymbol-mangling-version=v0");
|
if compiler.stage == 0 {
|
||||||
|
if use_new_symbol_mangling {
|
||||||
|
rustflags.arg("-Zsymbol-mangling-version=v0");
|
||||||
|
} else {
|
||||||
|
rustflags.arg("-Zsymbol-mangling-version=legacy");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rustflags.arg("-Zsymbol-mangling-version=legacy");
|
if use_new_symbol_mangling {
|
||||||
|
rustflags.arg("-Csymbol-mangling-version=v0");
|
||||||
|
} else {
|
||||||
|
rustflags.arg("-Csymbol-mangling-version=legacy");
|
||||||
|
rustflags.arg("-Zunstable-options");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`,
|
// FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`,
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 8a0bb3c96e71927b80fa2286d7a5a5f2547c6aa4
|
Subproject commit d3740fb7aad0ea4a80ae20f64dee3a8cfc0c5c3c
|
@ -1 +1 @@
|
|||||||
Subproject commit 06f9e61931bcf58b91dfe6c924057e42ce273ee1
|
Subproject commit f8ba2f12df60ee19b96de24ae5b73af3de8a446b
|
@ -1 +1 @@
|
|||||||
Subproject commit 9bf0028b557798ddd07a6f652e4d0c635d3d6620
|
Subproject commit 875464457c4104686faf667f47848aa7b0f0a744
|
@ -1350,17 +1350,23 @@ impl Clean<Type> for hir::Ty<'_> {
|
|||||||
}
|
}
|
||||||
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
|
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
|
let length = match length {
|
||||||
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
|
hir::ArrayLen::Infer(_, _) => "_".to_string(),
|
||||||
// as we currently do not supply the parent generics to anonymous constants
|
hir::ArrayLen::Body(anon_const) => {
|
||||||
// but do allow `ConstKind::Param`.
|
let def_id = cx.tcx.hir().local_def_id(anon_const.hir_id);
|
||||||
//
|
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
|
||||||
// `const_eval_poly` tries to to first substitute generic parameters which
|
// as we currently do not supply the parent generics to anonymous constants
|
||||||
// results in an ICE while manually constructing the constant and using `eval`
|
// but do allow `ConstKind::Param`.
|
||||||
// does nothing for `ConstKind::Param`.
|
//
|
||||||
let ct = ty::Const::from_anon_const(cx.tcx, def_id);
|
// `const_eval_poly` tries to to first substitute generic parameters which
|
||||||
let param_env = cx.tcx.param_env(def_id);
|
// results in an ICE while manually constructing the constant and using `eval`
|
||||||
let length = print_const(cx, ct.eval(cx.tcx, param_env));
|
// does nothing for `ConstKind::Param`.
|
||||||
|
let ct = ty::Const::from_anon_const(cx.tcx, def_id);
|
||||||
|
let param_env = cx.tcx.param_env(def_id);
|
||||||
|
print_const(cx, ct.eval(cx.tcx, param_env))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Array(box ty.clean(cx), length)
|
Array(box ty.clean(cx), length)
|
||||||
}
|
}
|
||||||
TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
|
TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
|
||||||
|
12
src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs
Normal file
12
src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// To avoid having to `or` gate `_` as an expr.
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
|
|
||||||
|
fn foo() -> [u8; _] {
|
||||||
|
//~^ ERROR the const placeholder `_` is not allowed within types on item signatures for generics
|
||||||
|
// FIXME(generic_arg_infer): this error message should say in the return type or sth like that.
|
||||||
|
[0; 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
error[E0121]: the const placeholder `_` is not allowed within types on item signatures for generics
|
||||||
|
--> $DIR/array-in-sig.rs:4:18
|
||||||
|
|
|
||||||
|
LL | fn foo() -> [u8; _] {
|
||||||
|
| ^ not allowed in type signatures
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0121`.
|
@ -0,0 +1,13 @@
|
|||||||
|
// run-pass
|
||||||
|
|
||||||
|
// To avoid having to `or` gate `_` as an expr.
|
||||||
|
#![feature(generic_arg_infer)]
|
||||||
|
|
||||||
|
fn foo() -> [u8; 3] {
|
||||||
|
let x: [u8; _] = [0; _];
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!([0; _], foo());
|
||||||
|
}
|
@ -18,7 +18,5 @@ fn main() {
|
|||||||
let a: All<_, _, _>;
|
let a: All<_, _, _>;
|
||||||
all_fn();
|
all_fn();
|
||||||
let v: [u8; _];
|
let v: [u8; _];
|
||||||
//~^ ERROR in expressions
|
|
||||||
let v: [u8; 10] = [0; _];
|
let v: [u8; 10] = [0; _];
|
||||||
//~^ ERROR in expressions
|
|
||||||
}
|
}
|
@ -10,18 +10,6 @@ error: expected identifier, found reserved identifier `_`
|
|||||||
LL | fn bad_infer_fn<_>() {}
|
LL | fn bad_infer_fn<_>() {}
|
||||||
| ^ expected identifier, found reserved identifier
|
| ^ expected identifier, found reserved identifier
|
||||||
|
|
||||||
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
|
||||||
--> $DIR/infer-arg-test.rs:20:15
|
|
||||||
|
|
|
||||||
LL | let v: [u8; _];
|
|
||||||
| ^ `_` not allowed here
|
|
||||||
|
|
||||||
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
|
||||||
--> $DIR/infer-arg-test.rs:22:25
|
|
||||||
|
|
|
||||||
LL | let v: [u8; 10] = [0; _];
|
|
||||||
| ^ `_` not allowed here
|
|
||||||
|
|
||||||
error[E0392]: parameter `_` is never used
|
error[E0392]: parameter `_` is never used
|
||||||
--> $DIR/infer-arg-test.rs:7:17
|
--> $DIR/infer-arg-test.rs:7:17
|
||||||
|
|
|
|
||||||
@ -31,6 +19,6 @@ LL | struct BadInfer<_>;
|
|||||||
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
|
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
= help: if you intended `_` to be a const parameter, use `const _: usize` instead
|
= help: if you intended `_` to be a const parameter, use `const _: usize` instead
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0392`.
|
For more information about this error, try `rustc --explain E0392`.
|
@ -1,5 +1,35 @@
|
|||||||
|
error[E0658]: using `_` for array lengths is unstable
|
||||||
|
--> $DIR/feature-gate-generic_arg_infer.rs:11:27
|
||||||
|
|
|
||||||
|
LL | let _x: [u8; 3] = [0; _];
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
|
||||||
|
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
--> $DIR/feature-gate-generic_arg_infer.rs:11:27
|
||||||
|
|
|
||||||
|
LL | let _x: [u8; 3] = [0; _];
|
||||||
|
| ^ `_` not allowed here
|
||||||
|
|
||||||
|
error[E0658]: using `_` for array lengths is unstable
|
||||||
|
--> $DIR/feature-gate-generic_arg_infer.rs:14:18
|
||||||
|
|
|
||||||
|
LL | let _y: [u8; _] = [0; 3];
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
|
||||||
|
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
--> $DIR/feature-gate-generic_arg_infer.rs:14:18
|
||||||
|
|
|
||||||
|
LL | let _y: [u8; _] = [0; 3];
|
||||||
|
| ^ `_` not allowed here
|
||||||
|
|
||||||
error[E0747]: type provided when a constant was expected
|
error[E0747]: type provided when a constant was expected
|
||||||
--> $DIR/feature-gate-generic_arg_infer.rs:11:20
|
--> $DIR/feature-gate-generic_arg_infer.rs:20:20
|
||||||
|
|
|
|
||||||
LL | let _x = foo::<_>([1,2]);
|
LL | let _x = foo::<_>([1,2]);
|
||||||
| ^
|
| ^
|
||||||
@ -7,6 +37,7 @@ LL | let _x = foo::<_>([1,2]);
|
|||||||
= help: const arguments cannot yet be inferred with `_`
|
= help: const arguments cannot yet be inferred with `_`
|
||||||
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0747`.
|
Some errors have detailed explanations: E0658, E0747.
|
||||||
|
For more information about an error, try `rustc --explain E0658`.
|
||||||
|
@ -7,7 +7,17 @@ fn foo<const N: usize>(_: [u8; N]) -> [u8; N] {
|
|||||||
[0; N]
|
[0; N]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
let _x: [u8; 3] = [0; _];
|
||||||
|
//[normal]~^ ERROR: using `_` for array lengths is unstable
|
||||||
|
//[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
let _y: [u8; _] = [0; 3];
|
||||||
|
//[normal]~^ ERROR: using `_` for array lengths is unstable
|
||||||
|
//[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _x = foo::<_>([1,2]);
|
let _x = foo::<_>([1,2]);
|
||||||
//[normal]~^ ERROR: type provided when a constant was expected
|
//[normal]~^ ERROR: type provided when a constant was expected
|
||||||
|
let _y = bar();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
|
|||||||
if let ItemKind::Struct(data, _) = &item.kind;
|
if let ItemKind::Struct(data, _) = &item.kind;
|
||||||
if let Some(last_field) = data.fields().last();
|
if let Some(last_field) = data.fields().last();
|
||||||
if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind;
|
if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind;
|
||||||
|
if let rustc_hir::ArrayLen::Body(length) = length;
|
||||||
|
|
||||||
// Then check if that that array zero-sized
|
// Then check if that that array zero-sized
|
||||||
let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
|
let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
|
||||||
|
@ -6,7 +6,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
|
|||||||
use rustc_ast::LitIntType;
|
use rustc_ast::LitIntType;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
|
use rustc_hir::{ArrayLen, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
@ -567,7 +567,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||||||
bind!(self, value, length);
|
bind!(self, value, length);
|
||||||
kind!("Repeat({value}, {length})");
|
kind!("Repeat({value}, {length})");
|
||||||
self.expr(value);
|
self.expr(value);
|
||||||
self.body(field!(length.body));
|
match length.value {
|
||||||
|
ArrayLen::Infer(..) => out!("if let ArrayLen::Infer(..) = length;"),
|
||||||
|
ArrayLen::Body(anon_const) => {
|
||||||
|
bind!(self, anon_const);
|
||||||
|
out!("if let ArrayLen::Body({anon_const}) = {length};");
|
||||||
|
self.body(field!(anon_const.body));
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Err => kind!("Err"),
|
ExprKind::Err => kind!("Err"),
|
||||||
ExprKind::DropTemps(expr) => {
|
ExprKind::DropTemps(expr) => {
|
||||||
|
@ -334,12 +334,17 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
|
|||||||
println!("{}anon_const:", ind);
|
println!("{}anon_const:", ind);
|
||||||
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
|
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
|
||||||
},
|
},
|
||||||
hir::ExprKind::Repeat(val, ref anon_const) => {
|
hir::ExprKind::Repeat(val, length) => {
|
||||||
println!("{}Repeat", ind);
|
println!("{}Repeat", ind);
|
||||||
println!("{}value:", ind);
|
println!("{}value:", ind);
|
||||||
print_expr(cx, val, indent + 1);
|
print_expr(cx, val, indent + 1);
|
||||||
println!("{}repeat count:", ind);
|
println!("{}repeat count:", ind);
|
||||||
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
|
match length {
|
||||||
|
hir::ArrayLen::Infer(_, _) => println!("{}repeat count: _", ind),
|
||||||
|
hir::ArrayLen::Body(anon_const) => {
|
||||||
|
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
hir::ExprKind::Err => {
|
hir::ExprKind::Err => {
|
||||||
println!("{}Err", ind);
|
println!("{}Err", ind);
|
||||||
|
@ -8,7 +8,7 @@ use rustc_hir::HirIdMap;
|
|||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId,
|
BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId,
|
||||||
InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt,
|
InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt,
|
||||||
StmtKind, Ty, TyKind, TypeBinding,
|
StmtKind, Ty, TyKind, TypeBinding, ArrayLen
|
||||||
};
|
};
|
||||||
use rustc_lexer::{tokenize, TokenKind};
|
use rustc_lexer::{tokenize, TokenKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -170,6 +170,14 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eq_array_length(&mut self, left: ArrayLen, right: ArrayLen) -> bool {
|
||||||
|
match (left, right) {
|
||||||
|
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
|
||||||
|
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body),
|
||||||
|
(_, _) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
|
pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
|
||||||
let cx = self.inner.cx;
|
let cx = self.inner.cx;
|
||||||
let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value);
|
let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value);
|
||||||
@ -194,8 +202,8 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let is_eq = match (
|
let is_eq = match (
|
||||||
&reduce_exprkind(self.inner.cx, &left.kind),
|
reduce_exprkind(self.inner.cx, &left.kind),
|
||||||
&reduce_exprkind(self.inner.cx, &right.kind),
|
reduce_exprkind(self.inner.cx, &right.kind),
|
||||||
) {
|
) {
|
||||||
(&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
|
(&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
|
||||||
lb == rb && l_mut == r_mut && self.eq_expr(le, re)
|
lb == rb && l_mut == r_mut && self.eq_expr(le, re)
|
||||||
@ -232,7 +240,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
},
|
},
|
||||||
(&ExprKind::Index(la, li), &ExprKind::Index(ra, ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
|
(&ExprKind::Index(la, li), &ExprKind::Index(ra, ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
|
||||||
(&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
|
(&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
|
||||||
self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
|
self.eq_expr(lc, rc) && self.eq_expr(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r))
|
||||||
},
|
},
|
||||||
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
|
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
|
||||||
self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
|
self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
|
||||||
@ -253,8 +261,8 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
(&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
|
(&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
|
||||||
self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
|
self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
|
||||||
},
|
},
|
||||||
(&ExprKind::Repeat(le, ref ll_id), &ExprKind::Repeat(re, ref rl_id)) => {
|
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
|
||||||
self.eq_expr(le, re) && self.eq_body(ll_id.body, rl_id.body)
|
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
|
||||||
},
|
},
|
||||||
(&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
|
(&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
|
||||||
(&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
|
(&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
|
||||||
@ -391,8 +399,8 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
|
fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
|
||||||
match (&left.kind, &right.kind) {
|
match (&left.kind, &right.kind) {
|
||||||
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
|
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
|
||||||
(&TyKind::Array(lt, ref ll_id), &TyKind::Array(rt, ref rl_id)) => {
|
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => {
|
||||||
self.eq_ty(lt, rt) && self.eq_body(ll_id.body, rl_id.body)
|
self.eq_ty(lt, rt) && self.eq_array_length(ll, rl)
|
||||||
},
|
},
|
||||||
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
|
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
|
||||||
l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
|
l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
|
||||||
@ -714,9 +722,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
ExprKind::ConstBlock(ref l_id) => {
|
ExprKind::ConstBlock(ref l_id) => {
|
||||||
self.hash_body(l_id.body);
|
self.hash_body(l_id.body);
|
||||||
},
|
},
|
||||||
ExprKind::Repeat(e, ref l_id) => {
|
ExprKind::Repeat(e, len) => {
|
||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
self.hash_body(l_id.body);
|
self.hash_array_length(len);
|
||||||
},
|
},
|
||||||
ExprKind::Ret(ref e) => {
|
ExprKind::Ret(ref e) => {
|
||||||
if let Some(e) = *e {
|
if let Some(e) = *e {
|
||||||
@ -906,9 +914,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
TyKind::Slice(ty) => {
|
TyKind::Slice(ty) => {
|
||||||
self.hash_ty(ty);
|
self.hash_ty(ty);
|
||||||
},
|
},
|
||||||
TyKind::Array(ty, anon_const) => {
|
&TyKind::Array(ty, len) => {
|
||||||
self.hash_ty(ty);
|
self.hash_ty(ty);
|
||||||
self.hash_body(anon_const.body);
|
self.hash_array_length(len);
|
||||||
},
|
},
|
||||||
TyKind::Ptr(ref mut_ty) => {
|
TyKind::Ptr(ref mut_ty) => {
|
||||||
self.hash_ty(mut_ty.ty);
|
self.hash_ty(mut_ty.ty);
|
||||||
@ -953,6 +961,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash_array_length(&mut self, length: ArrayLen) {
|
||||||
|
match length {
|
||||||
|
ArrayLen::Infer(..) => {}
|
||||||
|
ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hash_body(&mut self, body_id: BodyId) {
|
pub fn hash_body(&mut self, body_id: BodyId) {
|
||||||
// swap out TypeckResults when hashing a body
|
// swap out TypeckResults when hashing a body
|
||||||
let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id));
|
let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id));
|
||||||
|
@ -79,7 +79,7 @@ use rustc_hir::{
|
|||||||
def, Arm, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl,
|
def, Arm, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl,
|
||||||
ForeignItem, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local,
|
ForeignItem, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local,
|
||||||
MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem,
|
MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem,
|
||||||
TraitItemKind, TraitRef, TyKind, UnOp,
|
TraitItemKind, TraitRef, TyKind, UnOp, ArrayLen
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||||
use rustc_middle::hir::exports::Export;
|
use rustc_middle::hir::exports::Export;
|
||||||
@ -703,8 +703,9 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
|
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
|
||||||
ExprKind::Repeat(x, y) => if_chain! {
|
ExprKind::Repeat(x, len) => if_chain! {
|
||||||
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(y.body).value.kind;
|
if let ArrayLen::Body(len) = len;
|
||||||
|
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind;
|
||||||
if let LitKind::Int(v, _) = const_lit.node;
|
if let LitKind::Int(v, _) = const_lit.node;
|
||||||
if v <= 32 && is_default_equivalent(cx, x);
|
if v <= 32 && is_default_equivalent(cx, x);
|
||||||
then {
|
then {
|
||||||
|
@ -2,7 +2,8 @@ if_chain! {
|
|||||||
if let ExprKind::Repeat(value, length) = expr.kind;
|
if let ExprKind::Repeat(value, length) = expr.kind;
|
||||||
if let ExprKind::Lit(ref lit) = value.kind;
|
if let ExprKind::Lit(ref lit) = value.kind;
|
||||||
if let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node;
|
if let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node;
|
||||||
let expr1 = &cx.tcx.hir().body(length.body).value;
|
if let ArrayLen::Body(anon_const) = length;
|
||||||
|
let expr1 = &cx.tcx.hir().body(anon_const.body).value;
|
||||||
if let ExprKind::Lit(ref lit1) = expr1.kind;
|
if let ExprKind::Lit(ref lit1) = expr1.kind;
|
||||||
if let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node;
|
if let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node;
|
||||||
then {
|
then {
|
||||||
|
Loading…
Reference in New Issue
Block a user