Skip to content

Commit

Permalink
Auto merge of rust-lang#122524 - cuviper:beta-next, r=cuviper
Browse files Browse the repository at this point in the history
[beta] backports

- AST validation: Improve handling of inherent impls nested within functions and anon consts rust-lang#122004
- Downgrade const eval dangling ptr in final to future incompat lint rust-lang#122204

r? cuviper
  • Loading branch information
bors committed Mar 15, 2024
2 parents 339fb69 + 6b0992f commit 2bcca41
Show file tree
Hide file tree
Showing 17 changed files with 1,118 additions and 136 deletions.
57 changes: 30 additions & 27 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,35 +925,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
only_trait: only_trait.then_some(()),
};

self.visibility_not_permitted(
&item.vis,
errors::VisibilityNotPermittedNote::IndividualImplItems,
);
if let &Unsafe::Yes(span) = unsafety {
self.dcx().emit_err(errors::InherentImplCannotUnsafe {
span: self_ty.span,
annotation_span: span,
annotation: "unsafe",
self_ty: self_ty.span,
});
}
if let &ImplPolarity::Negative(span) = polarity {
self.dcx().emit_err(error(span, "negative", false));
}
if let &Defaultness::Default(def_span) = defaultness {
self.dcx().emit_err(error(def_span, "`default`", true));
}
if let &Const::Yes(span) = constness {
self.dcx().emit_err(error(span, "`const`", true));
}
self.with_in_trait_impl(None, |this| {
this.visibility_not_permitted(
&item.vis,
errors::VisibilityNotPermittedNote::IndividualImplItems,
);
if let &Unsafe::Yes(span) = unsafety {
this.dcx().emit_err(errors::InherentImplCannotUnsafe {
span: self_ty.span,
annotation_span: span,
annotation: "unsafe",
self_ty: self_ty.span,
});
}
if let &ImplPolarity::Negative(span) = polarity {
this.dcx().emit_err(error(span, "negative", false));
}
if let &Defaultness::Default(def_span) = defaultness {
this.dcx().emit_err(error(def_span, "`default`", true));
}
if let &Const::Yes(span) = constness {
this.dcx().emit_err(error(span, "`const`", true));
}

self.visit_vis(&item.vis);
self.visit_ident(item.ident);
self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| {
this.visit_generics(generics)
this.visit_vis(&item.vis);
this.visit_ident(item.ident);
this.with_tilde_const(
Some(DisallowTildeConstContext::Impl(item.span)),
|this| this.visit_generics(generics),
);
this.visit_ty(self_ty);
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
});
self.visit_ty(self_ty);
walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl);
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
}
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ pub(crate) struct DanglingPtrInFinal {
pub kind: InternKind,
}

#[derive(Diagnostic)]
#[derive(LintDiagnostic)]
#[diag(const_eval_mutable_ptr_in_final)]
pub(crate) struct MutablePtrInFinal {
#[primary_span]
// rust-lang/rust#122153: This was marked as `#[primary_span]` under
// `derive(Diagnostic)`. Since we expect we may hard-error in future, we are
// keeping the field (and skipping it under `derive(LintDiagnostic)`).
#[skip_arg]
pub span: Span,
pub kind: InternKind,
}
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_const_eval/src/interpret/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::mir::interpret::{CtfeProvenance, InterpResult};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_session::lint;

use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
use crate::const_eval;
Expand Down Expand Up @@ -195,10 +196,13 @@ pub fn intern_const_alloc_recursive<
})?;
}
if found_bad_mutable_pointer {
return Err(ecx
.tcx
.dcx()
.emit_err(MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }));
let err_diag = MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
ecx.tcx.emit_node_span_lint(
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
ecx.best_lint_scope(),
err_diag.span,
err_diag,
)
}

Ok(())
Expand Down
46 changes: 46 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ declare_lint_pass! {
CENUM_IMPL_DROP_CAST,
COHERENCE_LEAK_CHECK,
CONFLICTING_REPR_HINTS,
CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
CONST_EVALUATABLE_UNCHECKED,
CONST_ITEM_MUTATION,
CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
Expand Down Expand Up @@ -2905,6 +2906,51 @@ declare_lint! {
@feature_gate = sym::strict_provenance;
}

declare_lint! {
/// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer
/// has leaked into the final value of a const expression.
///
/// ### Example
///
/// ```rust
/// pub enum JsValue {
/// Undefined,
/// Object(std::cell::Cell<bool>),
/// }
///
/// impl ::std::ops::Drop for JsValue {
/// fn drop(&mut self) {}
/// }
///
/// const UNDEFINED: &JsValue = &JsValue::Undefined;
///
/// fn main() {
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// In the 1.77 release, the const evaluation machinery adopted some
/// stricter rules to reject expressions with values that could
/// end up holding mutable references to state stored in static memory
/// (which is inherently immutable).
///
/// This is a [future-incompatible] lint to ease the transition to an error.
/// See [issue #122153] for more details.
///
/// [issue #122153]: https://github.com/rust-lang/rust/issues/122153
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
Warn,
"detects a mutable pointer that has leaked into final value of a const expression",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #122153 <https://github.com/rust-lang/rust/issues/122153>",
};
}

declare_lint! {
/// The `const_evaluatable_unchecked` lint detects a generic constant used
/// in a type.
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
#![feature(const_mut_refs)]
#![deny(const_eval_mutable_ptr_in_final_value)]
use std::intrinsics;

const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
//~^ error: mutable pointer in final value of constant
//~| WARNING this was previously accepted by the compiler

fn main() {}
25 changes: 24 additions & 1 deletion tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
error: encountered mutable pointer in final value of constant
--> $DIR/alloc_intrinsic_untyped.rs:6:1
--> $DIR/alloc_intrinsic_untyped.rs:7:1
|
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/alloc_intrinsic_untyped.rs:4:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Future incompatibility report: Future breakage diagnostic:
error: encountered mutable pointer in final value of constant
--> $DIR/alloc_intrinsic_untyped.rs:7:1
|
LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
note: the lint level is defined here
--> $DIR/alloc_intrinsic_untyped.rs:4:9
|
LL | #![deny(const_eval_mutable_ptr_in_final_value)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// check-pass
use std::cell::Cell;

pub enum JsValue {
Undefined,
Object(Cell<bool>),
}

impl ::std::ops::Drop for JsValue {
fn drop(&mut self) {}
}

const UNDEFINED: &JsValue = &JsValue::Undefined;
//~^ WARN encountered mutable pointer in final value of constant
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

fn main() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
warning: encountered mutable pointer in final value of constant
--> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default

warning: 1 warning emitted

Future incompatibility report: Future breakage diagnostic:
warning: encountered mutable pointer in final value of constant
--> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #122153 <https://github.com/rust-lang/rust/issues/122153>
= note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default

Loading

0 comments on commit 2bcca41

Please sign in to comment.