Restrict #[rustc_box]
to Box::new
calls
This commit is contained in:
parent
c4e0cd9660
commit
d845769557
9 changed files with 115 additions and 29 deletions
|
@ -22,9 +22,6 @@ ast_lowering_misplaced_impl_trait =
|
|||
ast_lowering_misplaced_assoc_ty_binding =
|
||||
associated type bounds are only allowed in where clauses and function signatures, not in {$position}
|
||||
|
||||
ast_lowering_rustc_box_attribute_error =
|
||||
#[rustc_box] requires precisely one argument and no other attributes are allowed
|
||||
|
||||
ast_lowering_underscore_expr_lhs_assign =
|
||||
in expressions, `_` can only be used on the left-hand side of an assignment
|
||||
.label = `_` not allowed here
|
||||
|
|
|
@ -87,13 +87,6 @@ pub struct MisplacedAssocTyBinding<'a> {
|
|||
pub position: DiagnosticArgFromDisplay<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering_rustc_box_attribute_error)]
|
||||
pub struct RustcBoxAttributeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering_underscore_expr_lhs_assign)]
|
||||
pub struct UnderscoreExprLhsAssign {
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::errors::{
|
|||
AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
|
||||
BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
|
||||
GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
|
||||
RustcBoxAttributeError, UnderscoreExprLhsAssign,
|
||||
UnderscoreExprLhsAssign,
|
||||
};
|
||||
use super::ResolverAstLoweringExt;
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||
|
@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
|
||||
ExprKind::Call(f, args) => {
|
||||
if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
|
||||
if let [inner] = &args[..] && e.attrs.len() == 1 {
|
||||
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
|
||||
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
|
||||
} else {
|
||||
let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
|
||||
hir::ExprKind::Err(guar)
|
||||
}
|
||||
} else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
|
||||
if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
|
||||
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
|
||||
} else {
|
||||
let f = self.lower_expr(f);
|
||||
|
|
|
@ -374,3 +374,9 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co
|
|||
} matched
|
||||
|
||||
mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
|
||||
|
||||
|
||||
mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
|
||||
.attributes = no other attributes may be applied
|
||||
.not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
|
||||
.missing_box = `#[rustc_box]` requires the `owned_box` lang item
|
||||
|
|
|
@ -888,3 +888,22 @@ pub enum MiscPatternSuggestion {
|
|||
start_span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_rustc_box_attribute_error)]
|
||||
pub struct RustcBoxAttributeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub reason: RustcBoxAttrReason,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum RustcBoxAttrReason {
|
||||
#[note(mir_build_attributes)]
|
||||
Attributes,
|
||||
#[note(mir_build_not_box)]
|
||||
NotBoxNew,
|
||||
#[note(mir_build_missing_box)]
|
||||
MissingBox,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::errors;
|
||||
use crate::thir::cx::region::Scope;
|
||||
use crate::thir::cx::Cx;
|
||||
use crate::thir::util::UserAnnotatedTyHelpers;
|
||||
|
@ -18,7 +19,7 @@ use rustc_middle::ty::subst::InternalSubsts;
|
|||
use rustc_middle::ty::{
|
||||
self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
|
||||
impl<'tcx> Cx<'tcx> {
|
||||
|
@ -262,6 +263,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expr_ty = self.typeck_results().expr_ty(expr);
|
||||
|
@ -322,6 +324,34 @@ impl<'tcx> Cx<'tcx> {
|
|||
fn_span: expr.span,
|
||||
}
|
||||
} else {
|
||||
let attrs = tcx.hir().attrs(expr.hir_id);
|
||||
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_box) {
|
||||
if attrs.len() != 1 {
|
||||
tcx.sess.emit_err(errors::RustcBoxAttributeError {
|
||||
span: attrs[0].span,
|
||||
reason: errors::RustcBoxAttrReason::Attributes,
|
||||
});
|
||||
} else if let Some(box_item) = tcx.lang_items().owned_box() {
|
||||
if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind
|
||||
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
|
||||
&& path.res.opt_def_id().map_or(false, |did| did == box_item)
|
||||
&& fn_path.ident.name == sym::new
|
||||
&& let [value] = args
|
||||
{
|
||||
return Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) } }
|
||||
} else {
|
||||
tcx.sess.emit_err(errors::RustcBoxAttributeError {
|
||||
span: expr.span,
|
||||
reason: errors::RustcBoxAttrReason::NotBoxNew
|
||||
});
|
||||
}
|
||||
} else {
|
||||
tcx.sess.emit_err(errors::RustcBoxAttributeError {
|
||||
span: attrs[0].span,
|
||||
reason: errors::RustcBoxAttrReason::MissingBox,
|
||||
});
|
||||
}
|
||||
}
|
||||
let adt_data =
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
|
||||
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
|
||||
|
|
|
@ -287,15 +287,12 @@ impl<'a> VecArgs<'a> {
|
|||
Some(VecArgs::Repeat(&args[0], &args[1]))
|
||||
} else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
|
||||
// `vec![a, b, c]` case
|
||||
if_chain! {
|
||||
if let hir::ExprKind::Box(boxed) = args[0].kind;
|
||||
if let hir::ExprKind::Array(args) = boxed.kind;
|
||||
then {
|
||||
return Some(VecArgs::Vec(args));
|
||||
}
|
||||
if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
|
||||
&& let hir::ExprKind::Array(args) = arg.kind {
|
||||
Some(VecArgs::Vec(args))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
None
|
||||
} else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
|
||||
Some(VecArgs::Vec(&[]))
|
||||
} else {
|
||||
|
|
18
tests/ui/attributes/rustc-box.rs
Normal file
18
tests/ui/attributes/rustc-box.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#![feature(rustc_attrs, stmt_expr_attributes)]
|
||||
|
||||
fn foo(_: u32, _: u32) {}
|
||||
fn bar(_: u32) {}
|
||||
|
||||
fn main() {
|
||||
#[rustc_box]
|
||||
Box::new(1); // OK
|
||||
#[rustc_box]
|
||||
Box::pin(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
|
||||
#[rustc_box]
|
||||
foo(1, 1); //~ ERROR `#[rustc_box]` attribute used incorrectly
|
||||
#[rustc_box]
|
||||
bar(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
|
||||
#[rustc_box] //~ ERROR `#[rustc_box]` attribute used incorrectly
|
||||
#[rustfmt::skip]
|
||||
Box::new(1);
|
||||
}
|
34
tests/ui/attributes/rustc-box.stderr
Normal file
34
tests/ui/attributes/rustc-box.stderr
Normal file
|
@ -0,0 +1,34 @@
|
|||
error: `#[rustc_box]` attribute used incorrectly
|
||||
--> $DIR/rustc-box.rs:10:5
|
||||
|
|
||||
LL | Box::pin(1);
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[rustc_box]` may only be applied to a `Box::new()` call
|
||||
|
||||
error: `#[rustc_box]` attribute used incorrectly
|
||||
--> $DIR/rustc-box.rs:12:5
|
||||
|
|
||||
LL | foo(1, 1);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[rustc_box]` may only be applied to a `Box::new()` call
|
||||
|
||||
error: `#[rustc_box]` attribute used incorrectly
|
||||
--> $DIR/rustc-box.rs:14:5
|
||||
|
|
||||
LL | bar(1);
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: `#[rustc_box]` may only be applied to a `Box::new()` call
|
||||
|
||||
error: `#[rustc_box]` attribute used incorrectly
|
||||
--> $DIR/rustc-box.rs:15:5
|
||||
|
|
||||
LL | #[rustc_box]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: no other attributes may be applied
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
Loading…
Add table
Reference in a new issue