mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 20:28:33 +00:00
Auto merge of #119053 - matthiaskrgr:rollup-hky3ld3, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #118880 (More expressions correctly are marked to end with curly braces) - #118928 (fix: Overlapping spans in delimited meta-vars) - #119022 (Remove unnecessary constness from ProjectionCandidate) - #119052 (Avoid overflow in GVN constant indexing.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
6a62871320
@ -40,15 +40,44 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|||||||
| Range(_, Some(e), _)
|
| Range(_, Some(e), _)
|
||||||
| Ret(Some(e))
|
| Ret(Some(e))
|
||||||
| Unary(_, e)
|
| Unary(_, e)
|
||||||
| Yield(Some(e)) => {
|
| Yield(Some(e))
|
||||||
|
| Yeet(Some(e))
|
||||||
|
| Become(e) => {
|
||||||
expr = e;
|
expr = e;
|
||||||
}
|
}
|
||||||
Closure(closure) => {
|
Closure(closure) => {
|
||||||
expr = &closure.body;
|
expr = &closure.body;
|
||||||
}
|
}
|
||||||
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
|
||||||
| TryBlock(..) | While(..) => break Some(expr),
|
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
|
||||||
_ => break None,
|
|
||||||
|
// FIXME: These can end in `}`, but changing these would break stable code.
|
||||||
|
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
|
||||||
|
break None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Break(_, None)
|
||||||
|
| Range(_, None, _)
|
||||||
|
| Ret(None)
|
||||||
|
| Yield(None)
|
||||||
|
| Array(_)
|
||||||
|
| Call(_, _)
|
||||||
|
| MethodCall(_)
|
||||||
|
| Tup(_)
|
||||||
|
| Lit(_)
|
||||||
|
| Cast(_, _)
|
||||||
|
| Type(_, _)
|
||||||
|
| Await(_, _)
|
||||||
|
| Field(_, _)
|
||||||
|
| Index(_, _, _)
|
||||||
|
| Underscore
|
||||||
|
| Path(_, _)
|
||||||
|
| Continue(_)
|
||||||
|
| Repeat(_, _)
|
||||||
|
| Paren(_)
|
||||||
|
| Try(_)
|
||||||
|
| Yeet(None)
|
||||||
|
| Err => break None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,13 @@ fn expand_macro<'cx>(
|
|||||||
target_sp.open = source_sp.open.with_ctxt(ctxt);
|
target_sp.open = source_sp.open.with_ctxt(ctxt);
|
||||||
target_sp.close = source_sp.close.with_ctxt(ctxt);
|
target_sp.close = source_sp.close.with_ctxt(ctxt);
|
||||||
}
|
}
|
||||||
|
(
|
||||||
|
TokenTree::Delimited(target_sp, ..),
|
||||||
|
mbe::TokenTree::MetaVar(source_sp, ..),
|
||||||
|
) => {
|
||||||
|
target_sp.open = source_sp.with_ctxt(ctxt);
|
||||||
|
target_sp.close = source_sp.with_ctxt(ctxt).shrink_to_hi();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let sp = rhs_tt.span().with_ctxt(ctxt);
|
let sp = rhs_tt.span().with_ctxt(ctxt);
|
||||||
tt.set_span(sp);
|
tt.set_span(sp);
|
||||||
|
@ -125,10 +125,8 @@ pub enum SelectionCandidate<'tcx> {
|
|||||||
|
|
||||||
/// This is a trait matching with a projected type as `Self`, and we found
|
/// This is a trait matching with a projected type as `Self`, and we found
|
||||||
/// an applicable bound in the trait definition. The `usize` is an index
|
/// an applicable bound in the trait definition. The `usize` is an index
|
||||||
/// into the list returned by `tcx.item_bounds`. The constness is the
|
/// into the list returned by `tcx.item_bounds`.
|
||||||
/// constness of the bound in the trait.
|
ProjectionCandidate(usize),
|
||||||
// FIXME(effects) do we need this constness
|
|
||||||
ProjectionCandidate(usize, ty::BoundConstness),
|
|
||||||
|
|
||||||
/// Implementation of a `Fn`-family trait by one of the anonymous types
|
/// Implementation of a `Fn`-family trait by one of the anonymous types
|
||||||
/// generated for an `||` expression.
|
/// generated for an `||` expression.
|
||||||
|
@ -644,12 +644,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
{
|
{
|
||||||
if let Some(offset) = self.evaluated[idx].as_ref()
|
if let Some(offset) = self.evaluated[idx].as_ref()
|
||||||
&& let Ok(offset) = self.ecx.read_target_usize(offset)
|
&& let Ok(offset) = self.ecx.read_target_usize(offset)
|
||||||
|
&& let Some(min_length) = offset.checked_add(1)
|
||||||
{
|
{
|
||||||
projection.to_mut()[i] = ProjectionElem::ConstantIndex {
|
projection.to_mut()[i] =
|
||||||
offset,
|
ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
|
||||||
min_length: offset + 1,
|
|
||||||
from_end: false,
|
|
||||||
};
|
|
||||||
} else if let Some(new_idx) = self.try_as_local(idx, location) {
|
} else if let Some(new_idx) = self.try_as_local(idx, location) {
|
||||||
projection.to_mut()[i] = ProjectionElem::Index(new_idx);
|
projection.to_mut()[i] = ProjectionElem::Index(new_idx);
|
||||||
self.reused_locals.insert(new_idx);
|
self.reused_locals.insert(new_idx);
|
||||||
|
@ -154,10 +154,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
.infcx
|
.infcx
|
||||||
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
|
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
|
||||||
|
|
||||||
// FIXME(effects) proper constness needed?
|
candidates.vec.extend(result.into_iter().map(|idx| ProjectionCandidate(idx)));
|
||||||
candidates.vec.extend(
|
|
||||||
result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
|
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
|
||||||
@ -585,7 +582,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(ty::Opaque, _) => {
|
ty::Alias(ty::Opaque, _) => {
|
||||||
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) {
|
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) {
|
||||||
// We do not generate an auto impl candidate for `impl Trait`s which already
|
// We do not generate an auto impl candidate for `impl Trait`s which already
|
||||||
// reference our auto trait.
|
// reference our auto trait.
|
||||||
//
|
//
|
||||||
|
@ -71,7 +71,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectionCandidate(idx, _) => {
|
ProjectionCandidate(idx) => {
|
||||||
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
let obligations = self.confirm_projection_candidate(obligation, idx)?;
|
||||||
ImplSource::Param(obligations)
|
ImplSource::Param(obligations)
|
||||||
}
|
}
|
||||||
@ -1313,7 +1313,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// If we have a projection type, make sure to normalize it so we replace it
|
// If we have a projection type, make sure to normalize it so we replace it
|
||||||
// with a fresh infer variable
|
// with a fresh infer variable
|
||||||
ty::Alias(ty::Projection | ty::Inherent, ..) => {
|
ty::Alias(ty::Projection | ty::Inherent, ..) => {
|
||||||
// FIXME(effects) this needs constness
|
|
||||||
let predicate = normalize_with_depth_to(
|
let predicate = normalize_with_depth_to(
|
||||||
self,
|
self,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
@ -1344,7 +1343,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// since it's either not `const Drop` (and we raise an error during selection),
|
// since it's either not `const Drop` (and we raise an error during selection),
|
||||||
// or it's an ADT (and we need to check for a custom impl during selection)
|
// or it's an ADT (and we need to check for a custom impl during selection)
|
||||||
_ => {
|
_ => {
|
||||||
// FIXME(effects) this needs constness
|
|
||||||
let predicate = self_ty.rebind(ty::TraitPredicate {
|
let predicate = self_ty.rebind(ty::TraitPredicate {
|
||||||
trait_ref: ty::TraitRef::from_lang_item(
|
trait_ref: ty::TraitRef::from_lang_item(
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
|
@ -1883,7 +1883,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
| BuiltinCandidate { .. }
|
| BuiltinCandidate { .. }
|
||||||
| TraitAliasCandidate
|
| TraitAliasCandidate
|
||||||
| ObjectCandidate(_)
|
| ObjectCandidate(_)
|
||||||
| ProjectionCandidate(..),
|
| ProjectionCandidate(_),
|
||||||
) => {
|
) => {
|
||||||
// We have a where clause so don't go around looking
|
// We have a where clause so don't go around looking
|
||||||
// for impls. Arbitrarily give param candidates priority
|
// for impls. Arbitrarily give param candidates priority
|
||||||
@ -1893,7 +1893,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
// here (see issue #50825).
|
// here (see issue #50825).
|
||||||
DropVictim::drop_if(!is_global(other_cand))
|
DropVictim::drop_if(!is_global(other_cand))
|
||||||
}
|
}
|
||||||
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
|
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
|
||||||
// Prefer these to a global where-clause bound
|
// Prefer these to a global where-clause bound
|
||||||
// (see issue #50825).
|
// (see issue #50825).
|
||||||
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
|
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
|
||||||
@ -1921,20 +1921,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
(ProjectionCandidate(i, _), ProjectionCandidate(j, _))
|
(ProjectionCandidate(i), ProjectionCandidate(j))
|
||||||
| (ObjectCandidate(i), ObjectCandidate(j)) => {
|
| (ObjectCandidate(i), ObjectCandidate(j)) => {
|
||||||
// Arbitrarily pick the lower numbered candidate for backwards
|
// Arbitrarily pick the lower numbered candidate for backwards
|
||||||
// compatibility reasons. Don't let this affect inference.
|
// compatibility reasons. Don't let this affect inference.
|
||||||
DropVictim::drop_if(i < j && !has_non_region_infer)
|
DropVictim::drop_if(i < j && !has_non_region_infer)
|
||||||
}
|
}
|
||||||
(ObjectCandidate(_), ProjectionCandidate(..))
|
(ObjectCandidate(_), ProjectionCandidate(_))
|
||||||
| (ProjectionCandidate(..), ObjectCandidate(_)) => {
|
| (ProjectionCandidate(_), ObjectCandidate(_)) => {
|
||||||
bug!("Have both object and projection candidate")
|
bug!("Have both object and projection candidate")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrarily give projection and object candidates priority.
|
// Arbitrarily give projection and object candidates priority.
|
||||||
(
|
(
|
||||||
ObjectCandidate(_) | ProjectionCandidate(..),
|
ObjectCandidate(_) | ProjectionCandidate(_),
|
||||||
ImplCandidate(..)
|
ImplCandidate(..)
|
||||||
| AutoImplCandidate
|
| AutoImplCandidate
|
||||||
| ClosureCandidate { .. }
|
| ClosureCandidate { .. }
|
||||||
@ -1964,7 +1964,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
| BuiltinCandidate { .. }
|
| BuiltinCandidate { .. }
|
||||||
| TraitAliasCandidate,
|
| TraitAliasCandidate,
|
||||||
ObjectCandidate(_) | ProjectionCandidate(..),
|
ObjectCandidate(_) | ProjectionCandidate(_),
|
||||||
) => DropVictim::No,
|
) => DropVictim::No,
|
||||||
|
|
||||||
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
|
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
|
||||||
|
104
tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
Normal file
104
tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
- // MIR for `constant_index_overflow` before GVN
|
||||||
|
+ // MIR for `constant_index_overflow` after GVN
|
||||||
|
|
||||||
|
fn constant_index_overflow(_1: &[T]) -> () {
|
||||||
|
debug x => _1;
|
||||||
|
let mut _0: ();
|
||||||
|
let _2: usize;
|
||||||
|
let mut _4: bool;
|
||||||
|
let mut _5: usize;
|
||||||
|
let mut _6: usize;
|
||||||
|
let mut _7: &[T];
|
||||||
|
let _8: usize;
|
||||||
|
let mut _9: usize;
|
||||||
|
let mut _10: bool;
|
||||||
|
let _11: usize;
|
||||||
|
let mut _12: usize;
|
||||||
|
let mut _13: bool;
|
||||||
|
let mut _14: T;
|
||||||
|
scope 1 {
|
||||||
|
debug a => _2;
|
||||||
|
let _3: T;
|
||||||
|
scope 2 {
|
||||||
|
debug b => _3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
- StorageLive(_2);
|
||||||
|
- _2 = const _ as usize (IntToInt);
|
||||||
|
+ nop;
|
||||||
|
+ _2 = const usize::MAX;
|
||||||
|
StorageLive(_3);
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
- _5 = _2;
|
||||||
|
+ _5 = const usize::MAX;
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = &(*_1);
|
||||||
|
_6 = core::slice::<impl [T]>::len(move _7) -> [return: bb1, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageDead(_7);
|
||||||
|
- _4 = Lt(move _5, move _6);
|
||||||
|
+ _4 = Lt(const usize::MAX, move _6);
|
||||||
|
switchInt(move _4) -> [0: bb4, otherwise: bb2];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_8);
|
||||||
|
- _8 = _2;
|
||||||
|
+ _8 = const usize::MAX;
|
||||||
|
_9 = Len((*_1));
|
||||||
|
- _10 = Lt(_8, _9);
|
||||||
|
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind unreachable];
|
||||||
|
+ _10 = Lt(const usize::MAX, _9);
|
||||||
|
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
- _3 = (*_1)[_8];
|
||||||
|
+ _3 = (*_1)[_2];
|
||||||
|
StorageDead(_8);
|
||||||
|
goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = const 0_usize;
|
||||||
|
_12 = Len((*_1));
|
||||||
|
- _13 = Lt(_11, _12);
|
||||||
|
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind unreachable];
|
||||||
|
+ _13 = Lt(const 0_usize, _12);
|
||||||
|
+ assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
- _3 = (*_1)[_11];
|
||||||
|
+ _3 = (*_1)[0 of 1];
|
||||||
|
StorageDead(_11);
|
||||||
|
goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_4);
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = _3;
|
||||||
|
_0 = opaque::<T>(move _14) -> [return: bb7, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_14);
|
||||||
|
StorageDead(_3);
|
||||||
|
- StorageDead(_2);
|
||||||
|
+ nop;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
104
tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
Normal file
104
tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
- // MIR for `constant_index_overflow` before GVN
|
||||||
|
+ // MIR for `constant_index_overflow` after GVN
|
||||||
|
|
||||||
|
fn constant_index_overflow(_1: &[T]) -> () {
|
||||||
|
debug x => _1;
|
||||||
|
let mut _0: ();
|
||||||
|
let _2: usize;
|
||||||
|
let mut _4: bool;
|
||||||
|
let mut _5: usize;
|
||||||
|
let mut _6: usize;
|
||||||
|
let mut _7: &[T];
|
||||||
|
let _8: usize;
|
||||||
|
let mut _9: usize;
|
||||||
|
let mut _10: bool;
|
||||||
|
let _11: usize;
|
||||||
|
let mut _12: usize;
|
||||||
|
let mut _13: bool;
|
||||||
|
let mut _14: T;
|
||||||
|
scope 1 {
|
||||||
|
debug a => _2;
|
||||||
|
let _3: T;
|
||||||
|
scope 2 {
|
||||||
|
debug b => _3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
- StorageLive(_2);
|
||||||
|
- _2 = const _ as usize (IntToInt);
|
||||||
|
+ nop;
|
||||||
|
+ _2 = const usize::MAX;
|
||||||
|
StorageLive(_3);
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
- _5 = _2;
|
||||||
|
+ _5 = const usize::MAX;
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = &(*_1);
|
||||||
|
_6 = core::slice::<impl [T]>::len(move _7) -> [return: bb1, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageDead(_7);
|
||||||
|
- _4 = Lt(move _5, move _6);
|
||||||
|
+ _4 = Lt(const usize::MAX, move _6);
|
||||||
|
switchInt(move _4) -> [0: bb4, otherwise: bb2];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_8);
|
||||||
|
- _8 = _2;
|
||||||
|
+ _8 = const usize::MAX;
|
||||||
|
_9 = Len((*_1));
|
||||||
|
- _10 = Lt(_8, _9);
|
||||||
|
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> [success: bb3, unwind continue];
|
||||||
|
+ _10 = Lt(const usize::MAX, _9);
|
||||||
|
+ assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const usize::MAX) -> [success: bb3, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
- _3 = (*_1)[_8];
|
||||||
|
+ _3 = (*_1)[_2];
|
||||||
|
StorageDead(_8);
|
||||||
|
goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = const 0_usize;
|
||||||
|
_12 = Len((*_1));
|
||||||
|
- _13 = Lt(_11, _12);
|
||||||
|
- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb5, unwind continue];
|
||||||
|
+ _13 = Lt(const 0_usize, _12);
|
||||||
|
+ assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> [success: bb5, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
- _3 = (*_1)[_11];
|
||||||
|
+ _3 = (*_1)[0 of 1];
|
||||||
|
StorageDead(_11);
|
||||||
|
goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_4);
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = _3;
|
||||||
|
_0 = opaque::<T>(move _14) -> [return: bb7, unwind continue];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_14);
|
||||||
|
StorageDead(_3);
|
||||||
|
- StorageDead(_2);
|
||||||
|
+ nop;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -609,6 +609,22 @@ fn indirect_static() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify that having constant index `u64::MAX` does not yield to an overflow in rustc.
|
||||||
|
fn constant_index_overflow<T: Copy>(x: &[T]) {
|
||||||
|
// CHECK-LABEL: fn constant_index_overflow(
|
||||||
|
// CHECK: debug a => [[a:_.*]];
|
||||||
|
// CHECK: debug b => [[b:_.*]];
|
||||||
|
// CHECK: [[a]] = const usize::MAX;
|
||||||
|
// CHECK-NOT: = (*_1)[{{.*}} of 0];
|
||||||
|
// CHECK: [[b]] = (*_1)[[[a]]];
|
||||||
|
// CHECK-NOT: = (*_1)[{{.*}} of 0];
|
||||||
|
// CHECK: [[b]] = (*_1)[0 of 1];
|
||||||
|
// CHECK-NOT: = (*_1)[{{.*}} of 0];
|
||||||
|
let a = u64::MAX as usize;
|
||||||
|
let b = if a < x.len() { x[a] } else { x[0] };
|
||||||
|
opaque(b)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
subexpression_elimination(2, 4, 5);
|
subexpression_elimination(2, 4, 5);
|
||||||
wrap_unwrap(5);
|
wrap_unwrap(5);
|
||||||
@ -627,6 +643,7 @@ fn main() {
|
|||||||
repeat();
|
repeat();
|
||||||
fn_pointers();
|
fn_pointers();
|
||||||
indirect_static();
|
indirect_static();
|
||||||
|
constant_index_overflow(&[5, 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
@ -653,3 +670,4 @@ fn identity<T>(x: T) -> T {
|
|||||||
// EMIT_MIR gvn.repeat.GVN.diff
|
// EMIT_MIR gvn.repeat.GVN.diff
|
||||||
// EMIT_MIR gvn.fn_pointers.GVN.diff
|
// EMIT_MIR gvn.fn_pointers.GVN.diff
|
||||||
// EMIT_MIR gvn.indirect_static.GVN.diff
|
// EMIT_MIR gvn.indirect_static.GVN.diff
|
||||||
|
// EMIT_MIR gvn.constant_index_overflow.GVN.diff
|
||||||
|
16
tests/ui/macros/issue-118786.rs
Normal file
16
tests/ui/macros/issue-118786.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// compile-flags: --crate-type lib -O -C debug-assertions=yes
|
||||||
|
|
||||||
|
// Regression test for issue 118786
|
||||||
|
|
||||||
|
macro_rules! make_macro {
|
||||||
|
($macro_name:tt) => {
|
||||||
|
macro_rules! $macro_name {
|
||||||
|
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
|
||||||
|
//~| ERROR macro expansion ignores token `{` and any following
|
||||||
|
//~| ERROR cannot find macro `macro_rules` in this scope
|
||||||
|
() => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_macro!((meow));
|
47
tests/ui/macros/issue-118786.stderr
Normal file
47
tests/ui/macros/issue-118786.stderr
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
error: macros that expand to items must be delimited with braces or followed by a semicolon
|
||||||
|
--> $DIR/issue-118786.rs:7:22
|
||||||
|
|
|
||||||
|
LL | macro_rules! $macro_name {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: change the delimiters to curly braces
|
||||||
|
|
|
||||||
|
LL | macro_rules! {} {
|
||||||
|
| ~ +
|
||||||
|
help: add a semicolon
|
||||||
|
|
|
||||||
|
LL | macro_rules! $macro_name; {
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: macro expansion ignores token `{` and any following
|
||||||
|
--> $DIR/issue-118786.rs:7:34
|
||||||
|
|
|
||||||
|
LL | macro_rules! $macro_name {
|
||||||
|
| ^
|
||||||
|
...
|
||||||
|
LL | make_macro!((meow));
|
||||||
|
| ------------------- caused by the macro expansion here
|
||||||
|
|
|
||||||
|
= note: the usage of `make_macro!` is likely invalid in item context
|
||||||
|
|
||||||
|
error: cannot find macro `macro_rules` in this scope
|
||||||
|
--> $DIR/issue-118786.rs:7:9
|
||||||
|
|
|
||||||
|
LL | macro_rules! $macro_name {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | make_macro!((meow));
|
||||||
|
| ------------------- in this macro invocation
|
||||||
|
|
|
||||||
|
note: maybe you have forgotten to define a name for this `macro_rules!`
|
||||||
|
--> $DIR/issue-118786.rs:7:9
|
||||||
|
|
|
||||||
|
LL | macro_rules! $macro_name {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | make_macro!((meow));
|
||||||
|
| ------------------- in this macro invocation
|
||||||
|
= note: this error originates in the macro `make_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
164
tests/ui/parser/bad-let-else-statement.rs
Normal file
164
tests/ui/parser/bad-let-else-statement.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#![feature(inline_const)]
|
||||||
|
#![feature(yeet_expr)]
|
||||||
|
#![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete
|
||||||
|
#![feature(explicit_tail_calls)]
|
||||||
|
|
||||||
|
fn a() {
|
||||||
|
let foo = {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
let foo = for i in 1..2 {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR `for...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() {
|
||||||
|
let foo = if true {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn d() {
|
||||||
|
let foo = loop {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR loop...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn e() {
|
||||||
|
let foo = match true {
|
||||||
|
true => 1,
|
||||||
|
false => 0
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X {a: i32}
|
||||||
|
fn f() {
|
||||||
|
let foo = X {
|
||||||
|
a: 1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g() {
|
||||||
|
let foo = while false {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//~^ ERROR `while...else` loops are not supported
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h() {
|
||||||
|
let foo = const {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i() {
|
||||||
|
let foo = &{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn j() {
|
||||||
|
let bar = 0;
|
||||||
|
let foo = bar = {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn k() {
|
||||||
|
let foo = 1 + {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn l() {
|
||||||
|
let foo = 1..{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn m() {
|
||||||
|
let foo = return {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() {
|
||||||
|
let foo = -{
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn o() -> Result<(), ()> {
|
||||||
|
let foo = do yeet {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() {
|
||||||
|
let foo = become {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q() {
|
||||||
|
let foo = |x: i32| {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
232
tests/ui/parser/bad-let-else-statement.stderr
Normal file
232
tests/ui/parser/bad-let-else-statement.stderr
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:9:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `for...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:18:7
|
||||||
|
|
|
||||||
|
LL | let foo = for i in 1..2 {
|
||||||
|
| --- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:29:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (if true {
|
||||||
|
LL | 1
|
||||||
|
LL | } else {
|
||||||
|
LL | 0
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `loop...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:38:7
|
||||||
|
|
|
||||||
|
LL | let foo = loop {
|
||||||
|
| ---- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:48:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (match true {
|
||||||
|
LL | true => 1,
|
||||||
|
LL | false => 0
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:58:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (X {
|
||||||
|
LL | a: 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `while...else` loops are not supported
|
||||||
|
--> $DIR/bad-let-else-statement.rs:67:7
|
||||||
|
|
|
||||||
|
LL | let foo = while false {
|
||||||
|
| ----- `else` is attached to this loop
|
||||||
|
LL | break;
|
||||||
|
LL | } else {
|
||||||
|
| _______^
|
||||||
|
LL | |
|
||||||
|
LL | | return;
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:76:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = (const {
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:85:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = &({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:95:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = bar = ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:104:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = 1 + ({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:113:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = 1..({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:122:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = return ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:131:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = -({
|
||||||
|
LL | 1
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:140:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = do yeet ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:149:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = become ({
|
||||||
|
LL | ()
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:158:5
|
||||||
|
|
|
||||||
|
LL | } else {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: wrap the expression in parentheses
|
||||||
|
|
|
||||||
|
LL ~ let foo = |x: i32| ({
|
||||||
|
LL | x
|
||||||
|
LL ~ }) else {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 17 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user