Auto merge of #116482 - matthewjasper:thir-unsafeck-inline-constants, r=b-naber
Fix inline const pattern unsafety checking in THIR Fix THIR unsafety checking of inline constants. - Steal THIR in THIR unsafety checking (if enabled) instead of MIR lowering. - Represent inline constants in THIR patterns.
This commit is contained in:
commit
848a387967
@ -775,12 +775,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||
rustc_hir_analysis::check_crate(tcx)?;
|
||||
|
||||
sess.time("MIR_borrow_checking", || {
|
||||
tcx.hir().par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id));
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
// Run THIR unsafety check because it's responsible for stealing
|
||||
// and deallocating THIR when enabled.
|
||||
tcx.ensure().thir_check_unsafety(def_id);
|
||||
tcx.ensure().mir_borrowck(def_id)
|
||||
});
|
||||
});
|
||||
|
||||
sess.time("MIR_effect_checking", || {
|
||||
for def_id in tcx.hir().body_owners() {
|
||||
tcx.ensure().thir_check_unsafety(def_id);
|
||||
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
|
||||
rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
|
||||
}
|
||||
|
@ -636,7 +636,8 @@ fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
|
||||
Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {}
|
||||
AscribeUserType { subpattern, .. }
|
||||
| Binding { subpattern: Some(subpattern), .. }
|
||||
| Deref { subpattern } => subpattern.walk_(it),
|
||||
| Deref { subpattern }
|
||||
| InlineConstant { subpattern, .. } => subpattern.walk_(it),
|
||||
Leaf { subpatterns } | Variant { subpatterns, .. } => {
|
||||
subpatterns.iter().for_each(|field| field.pattern.walk_(it))
|
||||
}
|
||||
@ -764,6 +765,22 @@ pub enum PatKind<'tcx> {
|
||||
value: mir::Const<'tcx>,
|
||||
},
|
||||
|
||||
/// Inline constant found while lowering a pattern.
|
||||
InlineConstant {
|
||||
/// [LocalDefId] of the constant, we need this so that we have a
|
||||
/// reference that can be used by unsafety checking to visit nested
|
||||
/// unevaluated constants.
|
||||
def: LocalDefId,
|
||||
/// If the inline constant is used in a range pattern, this subpattern
|
||||
/// represents the range (if both ends are inline constants, there will
|
||||
/// be multiple InlineConstant wrappers).
|
||||
///
|
||||
/// Otherwise, the actual pattern that the constant lowered to. As with
|
||||
/// other constants, inline constants are matched structurally where
|
||||
/// possible.
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
Range(Box<PatRange<'tcx>>),
|
||||
|
||||
/// Matches against a slice, checking the length and extracting elements.
|
||||
@ -924,6 +941,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{subpattern}")
|
||||
}
|
||||
PatKind::Constant { value } => write!(f, "{value}"),
|
||||
PatKind::InlineConstant { def: _, ref subpattern } => {
|
||||
write!(f, "{} (from inline const)", subpattern)
|
||||
}
|
||||
PatKind::Range(box PatRange { lo, hi, end }) => {
|
||||
write!(f, "{lo}")?;
|
||||
write!(f, "{end}")?;
|
||||
|
@ -233,16 +233,17 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
|
||||
}
|
||||
}
|
||||
Constant { value: _ } => {}
|
||||
InlineConstant { def: _, subpattern } => visitor.visit_pat(subpattern),
|
||||
Range(_) => {}
|
||||
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
|
||||
for subpattern in prefix.iter() {
|
||||
visitor.visit_pat(&subpattern);
|
||||
visitor.visit_pat(subpattern);
|
||||
}
|
||||
if let Some(pat) = slice {
|
||||
visitor.visit_pat(&pat);
|
||||
visitor.visit_pat(pat);
|
||||
}
|
||||
for subpattern in suffix.iter() {
|
||||
visitor.visit_pat(&subpattern);
|
||||
visitor.visit_pat(subpattern);
|
||||
}
|
||||
}
|
||||
Or { pats } => {
|
||||
|
@ -847,6 +847,10 @@ pub(super) fn visit_primary_bindings(
|
||||
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
|
||||
}
|
||||
|
||||
PatKind::InlineConstant { ref subpattern, .. } => {
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f)
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
|
||||
|
@ -204,6 +204,12 @@ fn simplify_match_pair<'pat>(
|
||||
Err(match_pair)
|
||||
}
|
||||
|
||||
PatKind::InlineConstant { subpattern: ref pattern, def: _ } => {
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatKind::Range(box PatRange { lo, hi, end }) => {
|
||||
let (range, bias) = match *lo.ty().kind() {
|
||||
ty::Char => {
|
||||
@ -229,8 +235,8 @@ fn simplify_match_pair<'pat>(
|
||||
// correct the comparison. This is achieved by XORing with a bias (see
|
||||
// pattern/_match.rs for another pertinent example of this pattern).
|
||||
//
|
||||
// Also, for performance, it's important to only do the second `try_to_bits` if
|
||||
// necessary.
|
||||
// Also, for performance, it's important to only do the second
|
||||
// `try_to_bits` if necessary.
|
||||
let lo = lo.try_to_bits(sz).unwrap() ^ bias;
|
||||
if lo <= min {
|
||||
let hi = hi.try_to_bits(sz).unwrap() ^ bias;
|
||||
|
@ -73,6 +73,7 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<
|
||||
PatKind::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||
|
||||
PatKind::AscribeUserType { .. }
|
||||
| PatKind::InlineConstant { .. }
|
||||
| PatKind::Array { .. }
|
||||
| PatKind::Wild
|
||||
| PatKind::Binding { .. }
|
||||
@ -111,6 +112,7 @@ pub(super) fn add_cases_to_switch<'pat>(
|
||||
| PatKind::Or { .. }
|
||||
| PatKind::Binding { .. }
|
||||
| PatKind::AscribeUserType { .. }
|
||||
| PatKind::InlineConstant { .. }
|
||||
| PatKind::Leaf { .. }
|
||||
| PatKind::Deref { .. }
|
||||
| PatKind::Error(_) => {
|
||||
|
@ -53,10 +53,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
|
||||
}
|
||||
|
||||
/// Construct the MIR for a given `DefId`.
|
||||
fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
|
||||
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
|
||||
tcx.ensure_with_value()
|
||||
.thir_check_unsafety(tcx.typeck_root_def_id(def.to_def_id()).expect_local());
|
||||
fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
||||
tcx.ensure_with_value().thir_abstract_const(def);
|
||||
if let Err(e) = tcx.check_match(def) {
|
||||
return construct_error(tcx, def, e);
|
||||
@ -65,20 +62,27 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
|
||||
let body = match tcx.thir_body(def) {
|
||||
Err(error_reported) => construct_error(tcx, def, error_reported),
|
||||
Ok((thir, expr)) => {
|
||||
// We ran all queries that depended on THIR at the beginning
|
||||
// of `mir_build`, so now we can steal it
|
||||
let thir = thir.steal();
|
||||
let build_mir = |thir: &Thir<'tcx>| match thir.body_type {
|
||||
thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig),
|
||||
thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty),
|
||||
};
|
||||
|
||||
tcx.ensure().check_match(def);
|
||||
// this must run before MIR dump, because
|
||||
// "not all control paths return a value" is reported here.
|
||||
//
|
||||
// maybe move the check to a MIR pass?
|
||||
tcx.ensure().check_liveness(def);
|
||||
|
||||
match thir.body_type {
|
||||
thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
|
||||
thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
|
||||
if tcx.sess.opts.unstable_opts.thir_unsafeck {
|
||||
// Don't steal here if THIR unsafeck is being used. Instead
|
||||
// steal in unsafeck. This is so that pattern inline constants
|
||||
// can be evaluated as part of building the THIR of the parent
|
||||
// function without a cycle.
|
||||
build_mir(&thir.borrow())
|
||||
} else {
|
||||
// We ran all queries that depended on THIR at the beginning
|
||||
// of `mir_build`, so now we can steal it
|
||||
build_mir(&thir.steal())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -124,7 +124,9 @@ fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
|
||||
/// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body.
|
||||
fn visit_inner_body(&mut self, def: LocalDefId) {
|
||||
if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
|
||||
let inner_thir = &inner_thir.borrow();
|
||||
// Runs all other queries that depend on THIR.
|
||||
self.tcx.ensure_with_value().mir_built(def);
|
||||
let inner_thir = &inner_thir.steal();
|
||||
let hir_context = self.tcx.hir().local_def_id_to_hir_id(def);
|
||||
let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
|
||||
inner_visitor.visit_expr(&inner_thir[expr]);
|
||||
@ -224,6 +226,7 @@ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
|
||||
PatKind::Wild |
|
||||
// these just wrap other patterns
|
||||
PatKind::Or { .. } |
|
||||
PatKind::InlineConstant { .. } |
|
||||
PatKind::AscribeUserType { .. } |
|
||||
PatKind::Error(_) => {}
|
||||
}
|
||||
@ -277,6 +280,9 @@ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
|
||||
visit::walk_pat(self, pat);
|
||||
self.inside_adt = old_inside_adt;
|
||||
}
|
||||
PatKind::InlineConstant { def, .. } => {
|
||||
self.visit_inner_body(*def);
|
||||
}
|
||||
_ => {
|
||||
visit::walk_pat(self, pat);
|
||||
}
|
||||
@ -788,7 +794,9 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
|
||||
}
|
||||
|
||||
let Ok((thir, expr)) = tcx.thir_body(def) else { return };
|
||||
let thir = &thir.borrow();
|
||||
// Runs all other queries that depend on THIR.
|
||||
tcx.ensure_with_value().mir_built(def);
|
||||
let thir = &thir.steal();
|
||||
// If `thir` is empty, a type error occurred, skip this body.
|
||||
if thir.exprs.is_empty() {
|
||||
return;
|
||||
|
@ -1326,7 +1326,8 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
|
||||
let ctor;
|
||||
let fields;
|
||||
match &pat.kind {
|
||||
PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern),
|
||||
PatKind::AscribeUserType { subpattern, .. }
|
||||
| PatKind::InlineConstant { subpattern, .. } => return mkpat(subpattern),
|
||||
PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat),
|
||||
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
|
||||
ctor = Wildcard;
|
||||
|
@ -27,6 +27,7 @@
|
||||
self, AdtDef, CanonicalUserTypeAnnotation, GenericArg, GenericArgsRef, Region, Ty, TyCtxt,
|
||||
TypeVisitableExt, UserType,
|
||||
};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use rustc_target::abi::{FieldIdx, Integer};
|
||||
|
||||
@ -88,15 +89,21 @@ fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
||||
fn lower_pattern_range_endpoint(
|
||||
&mut self,
|
||||
expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> Result<(Option<mir::Const<'tcx>>, Option<Ascription<'tcx>>), ErrorGuaranteed> {
|
||||
) -> Result<
|
||||
(Option<mir::Const<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
|
||||
ErrorGuaranteed,
|
||||
> {
|
||||
match expr {
|
||||
None => Ok((None, None)),
|
||||
None => Ok((None, None, None)),
|
||||
Some(expr) => {
|
||||
let (kind, ascr) = match self.lower_lit(expr) {
|
||||
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
|
||||
(kind, Some(ascription))
|
||||
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
|
||||
PatKind::InlineConstant { subpattern, def } => {
|
||||
(subpattern.kind, None, Some(def))
|
||||
}
|
||||
kind => (kind, None),
|
||||
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
|
||||
(kind, Some(ascription), None)
|
||||
}
|
||||
kind => (kind, None, None),
|
||||
};
|
||||
let value = if let PatKind::Constant { value } = kind {
|
||||
value
|
||||
@ -106,7 +113,7 @@ fn lower_pattern_range_endpoint(
|
||||
);
|
||||
return Err(self.tcx.sess.delay_span_bug(expr.span, msg));
|
||||
};
|
||||
Ok((Some(value), ascr))
|
||||
Ok((Some(value), ascr, inline_const))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,8 +184,8 @@ fn lower_pattern_range(
|
||||
return Err(self.tcx.sess.delay_span_bug(span, msg));
|
||||
}
|
||||
|
||||
let (lo, lo_ascr) = self.lower_pattern_range_endpoint(lo_expr)?;
|
||||
let (hi, hi_ascr) = self.lower_pattern_range_endpoint(hi_expr)?;
|
||||
let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?;
|
||||
let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?;
|
||||
|
||||
let lo = lo.unwrap_or_else(|| {
|
||||
// Unwrap is ok because the type is known to be numeric.
|
||||
@ -237,6 +244,12 @@ fn lower_pattern_range(
|
||||
};
|
||||
}
|
||||
}
|
||||
for inline_const in [lo_inline, hi_inline] {
|
||||
if let Some(def) = inline_const {
|
||||
kind =
|
||||
PatKind::InlineConstant { def, subpattern: Box::new(Pat { span, ty, kind }) };
|
||||
}
|
||||
}
|
||||
Ok(kind)
|
||||
}
|
||||
|
||||
@ -599,11 +612,9 @@ fn lower_inline_const(
|
||||
// const eval path below.
|
||||
// FIXME: investigate the performance impact of removing this.
|
||||
let lit_input = match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
|
||||
hir::ExprKind::Lit(ref lit) => {
|
||||
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
|
||||
}
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
|
||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
@ -633,13 +644,13 @@ fn lower_inline_const(
|
||||
if let Ok(Some(valtree)) =
|
||||
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
|
||||
{
|
||||
self.const_to_pat(
|
||||
let subpattern = self.const_to_pat(
|
||||
Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
id,
|
||||
span,
|
||||
None,
|
||||
)
|
||||
.kind
|
||||
);
|
||||
PatKind::InlineConstant { subpattern, def: def_id }
|
||||
} else {
|
||||
// If that fails, convert it to an opaque constant pattern.
|
||||
match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) {
|
||||
@ -822,6 +833,9 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
PatKind::Deref { subpattern: subpattern.fold_with(folder) }
|
||||
}
|
||||
PatKind::Constant { value } => PatKind::Constant { value },
|
||||
PatKind::InlineConstant { def, subpattern: ref pattern } => {
|
||||
PatKind::InlineConstant { def, subpattern: pattern.fold_with(folder) }
|
||||
}
|
||||
PatKind::Range(ref range) => PatKind::Range(range.clone()),
|
||||
PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice {
|
||||
prefix: prefix.fold_with(folder),
|
||||
|
@ -692,7 +692,7 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
|
||||
}
|
||||
PatKind::Deref { subpattern } => {
|
||||
print_indented!(self, "Deref { ", depth_lvl + 1);
|
||||
print_indented!(self, "subpattern: ", depth_lvl + 2);
|
||||
print_indented!(self, "subpattern:", depth_lvl + 2);
|
||||
self.print_pat(subpattern, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
@ -701,6 +701,13 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
|
||||
print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::InlineConstant { def, subpattern } => {
|
||||
print_indented!(self, "InlineConstant {", depth_lvl + 1);
|
||||
print_indented!(self, format!("def: {:?}", def), depth_lvl + 2);
|
||||
print_indented!(self, "subpattern:", depth_lvl + 2);
|
||||
self.print_pat(subpattern, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Range(pat_range) => {
|
||||
print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ LL | S::f();
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||
--> $DIR/async-unsafe-fn-call-in-safe.rs:24:5
|
||||
--> $DIR/async-unsafe-fn-call-in-safe.rs:26:5
|
||||
|
|
||||
LL | f();
|
||||
| ^^^ call to unsafe function
|
||||
|
@ -20,6 +20,10 @@ async fn g() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
S::f(); //[mir]~ ERROR call to unsafe function is unsafe
|
||||
f(); //[mir]~ ERROR call to unsafe function is unsafe
|
||||
S::f();
|
||||
//[mir]~^ ERROR call to unsafe function is unsafe
|
||||
//[thir]~^^ ERROR call to unsafe function `S::f` is unsafe
|
||||
f();
|
||||
//[mir]~^ ERROR call to unsafe function is unsafe
|
||||
//[thir]~^^ ERROR call to unsafe function `f` is unsafe
|
||||
}
|
||||
|
@ -14,6 +14,22 @@ LL | f();
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block
|
||||
--> $DIR/async-unsafe-fn-call-in-safe.rs:23:5
|
||||
|
|
||||
LL | S::f();
|
||||
| ^^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
|
||||
--> $DIR/async-unsafe-fn-call-in-safe.rs:26:5
|
||||
|
|
||||
LL | f();
|
||||
| ^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0133`.
|
||||
|
@ -11,4 +11,5 @@ fn main() {
|
||||
//[thir]~^^ call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
foo();
|
||||
//[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block
|
||||
//[thir]~^^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
}
|
||||
|
@ -1,3 +1,11 @@
|
||||
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:12:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:9:17
|
||||
|
|
||||
@ -6,6 +14,6 @@ LL | let a: [u8; foo()];
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0133`.
|
||||
|
@ -1,11 +1,13 @@
|
||||
// ignore-test This is currently broken
|
||||
// revisions: mir thir
|
||||
// [mir]ignore-test This is currently broken
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(inline_const_pat)]
|
||||
|
||||
const unsafe fn require_unsafe() -> usize { 1 }
|
||||
const unsafe fn require_unsafe() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match () {
|
||||
@ -14,4 +16,12 @@ fn main() {
|
||||
//~^ ERROR [E0133]
|
||||
} => (),
|
||||
}
|
||||
|
||||
match 1 {
|
||||
const {
|
||||
require_unsafe()
|
||||
//~^ ERROR [E0133]
|
||||
}..=4 => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
19
tests/ui/inline-const/pat-unsafe-err.thir.stderr
Normal file
19
tests/ui/inline-const/pat-unsafe-err.thir.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
|
||||
--> $DIR/pat-unsafe-err.rs:15:13
|
||||
|
|
||||
LL | require_unsafe();
|
||||
| ^^^^^^^^^^^^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
|
||||
--> $DIR/pat-unsafe-err.rs:22:13
|
||||
|
|
||||
LL | require_unsafe()
|
||||
| ^^^^^^^^^^^^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0133`.
|
@ -1,13 +1,15 @@
|
||||
// ignore-test This is currently broken
|
||||
// check-pass
|
||||
// revisions: mir thir
|
||||
// [mir]ignore-test This is currently broken
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![warn(unused_unsafe)]
|
||||
#![feature(inline_const_pat)]
|
||||
|
||||
const unsafe fn require_unsafe() -> usize { 1 }
|
||||
const unsafe fn require_unsafe() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
@ -18,5 +20,14 @@ fn main() {
|
||||
//~^ WARNING unnecessary `unsafe` block
|
||||
} => (),
|
||||
}
|
||||
|
||||
match 1 {
|
||||
const {
|
||||
unsafe {}
|
||||
//~^ WARNING unnecessary `unsafe` block
|
||||
require_unsafe()
|
||||
}..=4 => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
tests/ui/inline-const/pat-unsafe.thir.stderr
Normal file
26
tests/ui/inline-const/pat-unsafe.thir.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
warning: unnecessary `unsafe` block
|
||||
--> $DIR/pat-unsafe.rs:19:17
|
||||
|
|
||||
LL | unsafe {
|
||||
| ------ because it's nested under this `unsafe` block
|
||||
...
|
||||
LL | unsafe {}
|
||||
| ^^^^^^ unnecessary `unsafe` block
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/pat-unsafe.rs:7:9
|
||||
|
|
||||
LL | #![warn(unused_unsafe)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: unnecessary `unsafe` block
|
||||
--> $DIR/pat-unsafe.rs:26:17
|
||||
|
|
||||
LL | unsafe {
|
||||
| ------ because it's nested under this `unsafe` block
|
||||
...
|
||||
LL | unsafe {}
|
||||
| ^^^^^^ unnecessary `unsafe` block
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
14
tests/ui/pattern/non-structural-match-types.mir.stderr
Normal file
14
tests/ui/pattern/non-structural-match-types.mir.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: `{closure@$DIR/non-structural-match-types.rs:12:17: 12:19}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:12:9
|
||||
|
|
||||
LL | const { || {} } => {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `{async block@$DIR/non-structural-match-types.rs:15:17: 15:25}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:15:9
|
||||
|
|
||||
LL | const { async {} } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,4 +1,7 @@
|
||||
// edition:2021
|
||||
// revisions: mir thir
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(unreachable_code)]
|
||||
#![feature(const_async_blocks)]
|
||||
|
@ -1,14 +0,0 @@
|
||||
error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:9:9
|
||||
|
|
||||
LL | const { || {} } => {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:12:9
|
||||
|
|
||||
LL | const { async {} } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
14
tests/ui/pattern/non-structural-match-types.thir.stderr
Normal file
14
tests/ui/pattern/non-structural-match-types.thir.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: `{closure@$DIR/non-structural-match-types.rs:12:17: 12:19}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:12:9
|
||||
|
|
||||
LL | const { || {} } => {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `{async block@$DIR/non-structural-match-types.rs:15:17: 15:25}` cannot be used in patterns
|
||||
--> $DIR/non-structural-match-types.rs:15:9
|
||||
|
|
||||
LL | const { async {} } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user