From 9b6bdcd86b4e133c2e3a86088e7d583623fdc9df Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Tue, 4 Jul 2023 09:37:40 +0800 Subject: [PATCH 01/19] Suggest `x build library` for a custom toolchain that fails to load `core` --- compiler/rustc_metadata/messages.ftl | 3 +++ compiler/rustc_metadata/src/errors.rs | 16 ++++++++++++---- compiler/rustc_metadata/src/locator.rs | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 13b3dac85d1..cc58d51befd 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -25,6 +25,9 @@ metadata_conflicting_alloc_error_handler = metadata_conflicting_global_alloc = the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} +metadata_consider_adding_std = + consider adding the standard library to the sysroot with `x build library --target {$locator_triple}` + metadata_consider_building_std = consider building the standard library from source with `cargo build -Zbuild-std` diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index fca06c0f47c..91220629fb6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -623,6 +623,7 @@ pub struct CannotFindCrate { pub is_nightly_build: bool, pub profiler_runtime: Symbol, pub locator_triple: TargetTriple, + pub is_ui_testing: bool, } impl IntoDiagnostic<'_> for CannotFindCrate { @@ -646,12 +647,19 @@ impl IntoDiagnostic<'_> for CannotFindCrate { } else { diag.note(fluent::metadata_target_no_std_support); } - // NOTE: this suggests using rustup, even though the user may not have it installed. - // That's because they could choose to install it; or this may give them a hint which - // target they need to install from their distro. + if self.missing_core { - diag.help(fluent::metadata_consider_downloading_target); + if env!("CFG_RELEASE_CHANNEL") == "dev" && !self.is_ui_testing { + // Note: Emits the nicer suggestion only for the dev channel. + diag.help(fluent::metadata_consider_adding_std); + } else { + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + diag.help(fluent::metadata_consider_downloading_target); + } } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. // If it's not a dummy, that means someone added `extern crate std` explicitly and diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index a89d7b464e2..e91a6f34a78 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1125,6 +1125,7 @@ impl CrateError { is_nightly_build: sess.is_nightly_build(), profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, + is_ui_testing: sess.opts.unstable_opts.ui_testing, }); } } @@ -1141,6 +1142,7 @@ impl CrateError { is_nightly_build: sess.is_nightly_build(), profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), + is_ui_testing: sess.opts.unstable_opts.ui_testing, }); } } From 7dd5e3c1cd5c150f16261fef6a1efb76e70f022e Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 28 Jul 2023 11:31:31 +0200 Subject: [PATCH 02/19] Add regression test for resolving `--extern libc=test.rlib` I could not find a test for this particular use case. The closest I got was `tests/ui/imports/issue-37887.rs`, but that is a regression test for a different use case. --- tests/ui/imports/resolve-other-libc.rs | 14 ++++++++++++++ tests/ui/imports/resolve-other-libc.stderr | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/ui/imports/resolve-other-libc.rs create mode 100644 tests/ui/imports/resolve-other-libc.stderr diff --git a/tests/ui/imports/resolve-other-libc.rs b/tests/ui/imports/resolve-other-libc.rs new file mode 100644 index 00000000000..806d854ec89 --- /dev/null +++ b/tests/ui/imports/resolve-other-libc.rs @@ -0,0 +1,14 @@ +// Regression test for https://github.com/rust-lang/rust/issues/26043 + +// compile-flags: --extern libc=test.rlib + +// The error shall NOT be something similar to the following, because it +// indicates that `libc` was wrongly resolved to `libc` shipped with the +// compiler: +// +// error[E0658]: use of unstable library feature 'rustc_private': \ +// this crate is being loaded from the sysroot +// +extern crate libc; //~ ERROR: extern location for libc does not exist: test.rlib + +fn main() {} diff --git a/tests/ui/imports/resolve-other-libc.stderr b/tests/ui/imports/resolve-other-libc.stderr new file mode 100644 index 00000000000..e57b88e50c6 --- /dev/null +++ b/tests/ui/imports/resolve-other-libc.stderr @@ -0,0 +1,8 @@ +error: extern location for libc does not exist: test.rlib + --> $DIR/resolve-other-libc.rs:12:1 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 345d6b816b8b131bc592f2aa532e1b3aeef23d0b Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 14 Jul 2023 21:54:27 +0200 Subject: [PATCH 03/19] Revert "Temporarily switch invalid_reference_casting lint to allow-by-default" This reverts commit f25ad54a4d0febbcb2b7e951835228b7b2320b49. --- compiler/rustc_lint/src/reference_casting.rs | 3 +-- .../ui/const-generics/issues/issue-100313.rs | 1 + .../const-generics/issues/issue-100313.stderr | 12 +++++++-- tests/ui/lint/reference_casting.rs | 1 - tests/ui/lint/reference_casting.stderr | 26 ++++++++----------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d343aaf35d5..1a172dd6942 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -12,7 +12,6 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #![deny(invalid_reference_casting)] /// fn x(r: &i32) { /// unsafe { /// *(r as *const i32 as *mut i32) += 1; @@ -30,7 +29,7 @@ declare_lint! { /// `UnsafeCell` is the only way to obtain aliasable data that is considered /// mutable. INVALID_REFERENCE_CASTING, - Allow, + Deny, "casts of `&T` to `&mut T` without interior mutability" } diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs index 4e9d3626aa8..9a9d4721c84 100644 --- a/tests/ui/const-generics/issues/issue-100313.rs +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -9,6 +9,7 @@ impl T { unsafe { *(B as *const bool as *mut bool) = false; //~^ ERROR evaluation of constant value failed [E0080] + //~| ERROR casting `&T` to `&mut T` is undefined behavior } } } diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index d4b486376ca..17e4850bd12 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -1,3 +1,11 @@ +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(invalid_reference_casting)]` on by default + error[E0080]: evaluation of constant value failed --> $DIR/issue-100313.rs:10:13 | @@ -10,11 +18,11 @@ note: inside `T::<&true>::set_false` LL | *(B as *const bool as *mut bool) = false; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `_` - --> $DIR/issue-100313.rs:18:5 + --> $DIR/issue-100313.rs:19:5 | LL | x.set_false(); | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 9963820499e..745d7070143 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -1,7 +1,6 @@ // check-fail #![feature(ptr_from_ref)] -#![deny(invalid_reference_casting)] extern "C" { // N.B., mutability can be easily incorrect in FFI calls -- as diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index d5b9bbef643..d1dd1b32ff4 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -1,65 +1,61 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:20:9 + --> $DIR/reference_casting.rs:19:9 | LL | (*(a as *const _ as *mut String)).push_str(" world"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/reference_casting.rs:4:9 - | -LL | #![deny(invalid_reference_casting)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(invalid_reference_casting)]` on by default error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:22:9 + --> $DIR/reference_casting.rs:21:9 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:24:9 + --> $DIR/reference_casting.rs:23:9 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:26:25 + --> $DIR/reference_casting.rs:25:25 | LL | let _num = &mut *(num as *const i32 as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:28:25 + --> $DIR/reference_casting.rs:27:25 | LL | let _num = &mut *(num as *const i32).cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:30:20 + --> $DIR/reference_casting.rs:29:20 | LL | let _num = *{ num as *const i32 }.cast_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:32:9 + --> $DIR/reference_casting.rs:31:9 | LL | *std::ptr::from_ref(num).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:34:9 + --> $DIR/reference_casting.rs:33:9 | LL | *std::ptr::from_ref({ num }).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:36:9 + --> $DIR/reference_casting.rs:35:9 | LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:38:9 + --> $DIR/reference_casting.rs:37:9 | LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From f3dafe91ff753e3a801aa336d41be9eca75925bc Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 14 Jul 2023 22:10:14 +0200 Subject: [PATCH 04/19] Add support for deferred casting for the invalid_reference_casting lint --- compiler/rustc_lint/messages.ftl | 1 + compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_lint/src/lints.rs | 5 +- compiler/rustc_lint/src/reference_casting.rs | 97 +++++++++++++------- tests/ui/lint/reference_casting.rs | 3 + tests/ui/lint/reference_casting.stderr | 10 +- 6 files changed, 83 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 16e17fc9d6a..95f0b651962 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -319,6 +319,7 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + .label = casting happend here lint_lintpass_by_hand = implementing `LintPass` by hand .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 53089294fe2..96fd3ccf774 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -218,7 +218,7 @@ late_lint_methods!( BoxPointers: BoxPointers, PathStatements: PathStatements, LetUnderscore: LetUnderscore, - InvalidReferenceCasting: InvalidReferenceCasting, + InvalidReferenceCasting: InvalidReferenceCasting::default(), // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, NonUpperCaseGlobals: NonUpperCaseGlobals, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 968172693a9..6d774070ec4 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -746,7 +746,10 @@ pub enum InvalidFromUtf8Diag { // reference_casting.rs #[derive(LintDiagnostic)] #[diag(lint_invalid_reference_casting)] -pub struct InvalidReferenceCastingDiag; +pub struct InvalidReferenceCastingDiag { + #[label] + pub orig_cast: Option, +} // hidden_unicode_codepoints.rs #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 1a172dd6942..e6cab4cebe7 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -1,7 +1,8 @@ use rustc_ast::Mutability; -use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp}; -use rustc_middle::ty; -use rustc_span::sym; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, QPath, StmtKind, UnOp}; +use rustc_middle::ty::{self, TypeAndMut}; +use rustc_span::{sym, Span}; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; @@ -33,42 +34,74 @@ declare_lint! { "casts of `&T` to `&mut T` without interior mutability" } -declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); +#[derive(Default)] +pub struct InvalidReferenceCasting { + casted: FxHashMap, +} + +impl_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) { + let StmtKind::Local(local) = stmt.kind else { + return; + }; + let Local { init: Some(init), els: None, .. } = local else { + return; + }; + + if is_cast_from_const_to_mut(cx, init) { + self.casted.insert(local.pat.hir_id, init.span); + } + } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { return; }; - let e = e.peel_blocks(); - let e = if let ExprKind::Cast(e, t) = e.kind - && let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind { - e - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { - expr - } else { - return; - }; - - let e = e.peel_blocks(); - let e = if let ExprKind::Cast(e, t) = e.kind - && let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind { - e - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) { - arg - } else { - return; - }; - - let e = e.peel_blocks(); - if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() { - cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag); + if is_cast_from_const_to_mut(cx, e) { + cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag { orig_cast: None }); + } else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind + && let Res::Local(hir_id) = &path.res + && let Some(orig_cast) = self.casted.get(hir_id) { + cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag { orig_cast: Some(*orig_cast) }); } } } + +fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { + let e = e.peel_blocks(); + + // as *mut ... + let e = if let ExprKind::Cast(e, t) = e.kind + && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { + e + // .cast_mut() + } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { + expr + } else { + return false; + }; + + let e = e.peel_blocks(); + + // as *const ... + let e = if let ExprKind::Cast(e, t) = e.kind + && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { + e + // ptr::from_ref() + } else if let ExprKind::Call(path, [arg]) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) { + arg + } else { + return false; + }; + + let e = e.peel_blocks(); + matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(..)) +} diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 745d7070143..c3168cd4c01 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -36,6 +36,9 @@ fn main() { //~^ ERROR casting `&T` to `&mut T` is undefined behavior *(std::ptr::from_ref({ num }) as *mut i32) += 1; //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let value = num as *const i32 as *mut i32; + *value = 1; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior // Shouldn't be warned against println!("{}", *(num as *const _ as *const i16)); diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index d1dd1b32ff4..d9ce4b38387 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -60,5 +60,13 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:40:9 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +LL | *value = 1; + | ^^^^^^ + +error: aborting due to 11 previous errors From 50a46710a9c6942751930fa963e0d70d84128859 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 14 Jul 2023 22:15:28 +0200 Subject: [PATCH 05/19] Avoid linting on expression that are only UB with SB/TB --- compiler/rustc_lint/src/reference_casting.rs | 17 +++++- tests/ui/lint/reference_casting.rs | 5 +- tests/ui/lint/reference_casting.stderr | 56 ++++++++------------ 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index e6cab4cebe7..428bf750bbd 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -56,7 +56,20 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { + // &mut + let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind { + expr + // = ... + } else if let ExprKind::Assign(expr, _, _) = expr.kind { + expr + // += ... + } else if let ExprKind::AssignOp(_, expr, _) = expr.kind { + expr + } else { + return; + }; + + let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else { return; }; @@ -103,5 +116,5 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) }; let e = e.peel_blocks(); - matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(..)) + matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(_, _, Mutability::Not)) } diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index c3168cd4c01..aa946038c99 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -16,8 +16,6 @@ fn main() { let num = &3i32; let mut_num = &mut 3i32; - (*(a as *const _ as *mut String)).push_str(" world"); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior *(a as *const _ as *mut _) = String::from("Replaced"); //~^ ERROR casting `&T` to `&mut T` is undefined behavior *(a as *const _ as *mut String) += " world"; @@ -26,8 +24,6 @@ fn main() { //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const i32).cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = *{ num as *const i32 }.cast_mut(); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior *std::ptr::from_ref(num).cast_mut() += 1; //~^ ERROR casting `&T` to `&mut T` is undefined behavior *std::ptr::from_ref({ num }).cast_mut() += 1; @@ -41,6 +37,7 @@ fn main() { //~^ ERROR casting `&T` to `&mut T` is undefined behavior // Shouldn't be warned against + *(num as *const i32 as *mut i32); println!("{}", *(num as *const _ as *const i16)); println!("{}", *(mut_num as *mut _ as *mut i16)); ffi(a.as_ptr() as *mut _); diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index d9ce4b38387..22bc66264d0 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -1,72 +1,60 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:19:9 | -LL | (*(a as *const _ as *mut String)).push_str(" world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | *(a as *const _ as *mut _) = String::from("Replaced"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[deny(invalid_reference_casting)]` on by default error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:21:9 | -LL | *(a as *const _ as *mut _) = String::from("Replaced"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:23:9 - | LL | *(a as *const _ as *mut String) += " world"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:25:25 + --> $DIR/reference_casting.rs:23:20 | LL | let _num = &mut *(num as *const i32 as *mut i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:27:25 + --> $DIR/reference_casting.rs:25:20 | LL | let _num = &mut *(num as *const i32).cast_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:29:20 + --> $DIR/reference_casting.rs:27:9 | -LL | let _num = *{ num as *const i32 }.cast_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | *std::ptr::from_ref(num).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:29:9 + | +LL | *std::ptr::from_ref({ num }).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:31:9 | -LL | *std::ptr::from_ref(num).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:33:9 | -LL | *std::ptr::from_ref({ num }).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:35:9 - | -LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:37:9 - | LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:40:9 + --> $DIR/reference_casting.rs:36:9 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here LL | *value = 1; - | ^^^^^^ + | ^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors From 20a6b571063d33c4b1a786c558f74edbda3012ea Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 14 Jul 2023 22:25:47 +0200 Subject: [PATCH 06/19] Improve diagnostics of the invalid_reference_casting lint --- compiler/rustc_lint/messages.ftl | 5 +- compiler/rustc_lint/src/lints.rs | 15 ++- compiler/rustc_lint/src/reference_casting.rs | 20 +++- tests/ui/lint/reference_casting.rs | 91 ++++++++++++------- tests/ui/lint/reference_casting.stderr | 96 +++++++++++++------- 5 files changed, 151 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 95f0b651962..f482e3d7c12 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -318,7 +318,10 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable -lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` +lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + .label = casting happend here + +lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` .label = casting happend here lint_lintpass_by_hand = implementing `LintPass` by hand diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 6d774070ec4..a6a48bf4ffa 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -745,10 +745,17 @@ pub enum InvalidFromUtf8Diag { // reference_casting.rs #[derive(LintDiagnostic)] -#[diag(lint_invalid_reference_casting)] -pub struct InvalidReferenceCastingDiag { - #[label] - pub orig_cast: Option, +pub enum InvalidReferenceCastingDiag { + #[diag(lint_invalid_reference_casting_borrow_as_mut)] + BorrowAsMut { + #[label] + orig_cast: Option, + }, + #[diag(lint_invalid_reference_casting_assign_to_ref)] + AssignToRef { + #[label] + orig_cast: Option, + }, } // hidden_unicode_codepoints.rs diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 428bf750bbd..ed3d4721049 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -73,13 +73,25 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { return; }; - if is_cast_from_const_to_mut(cx, e) { - cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag { orig_cast: None }); + let orig_cast = if is_cast_from_const_to_mut(cx, e) { + None } else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind && let Res::Local(hir_id) = &path.res && let Some(orig_cast) = self.casted.get(hir_id) { - cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag { orig_cast: Some(*orig_cast) }); - } + Some(*orig_cast) + } else { + return; + }; + + cx.emit_spanned_lint( + INVALID_REFERENCE_CASTING, + expr.span, + if matches!(expr.kind, ExprKind::AddrOf(..)) { + InvalidReferenceCastingDiag::BorrowAsMut { orig_cast } + } else { + InvalidReferenceCastingDiag::AssignToRef { orig_cast } + }, + ); } } diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index aa946038c99..6e70626ef99 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -9,42 +9,63 @@ extern "C" { fn int_ffi(c: *mut i32); } -fn main() { +unsafe fn ref_to_mut() { + let num = &3i32; + + let _num = &mut *(num as *const i32 as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *std::ptr::from_ref(num).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + let deferred = num as *const i32 as *mut i32; + let _num = &mut *deferred; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior +} + +unsafe fn assign_to_ref() { let s = String::from("Hello"); let a = &s; - unsafe { - let num = &3i32; - let mut_num = &mut 3i32; + let num = &3i32; - *(a as *const _ as *mut _) = String::from("Replaced"); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *(a as *const _ as *mut String) += " world"; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = &mut *(num as *const i32 as *mut i32); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = &mut *(num as *const i32).cast_mut(); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *std::ptr::from_ref(num).cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *std::ptr::from_ref({ num }).cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *{ std::ptr::from_ref(num) }.cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *(std::ptr::from_ref({ num }) as *mut i32) += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let value = num as *const i32 as *mut i32; - *value = 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - - // Shouldn't be warned against - *(num as *const i32 as *mut i32); - println!("{}", *(num as *const _ as *const i16)); - println!("{}", *(mut_num as *mut _ as *mut i16)); - ffi(a.as_ptr() as *mut _); - int_ffi(num as *const _ as *mut _); - int_ffi(&3 as *const _ as *mut _); - let mut value = 3; - let value: *const i32 = &mut value; - *(value as *const i16 as *mut i16) = 42; - } + *(a as *const _ as *mut _) = String::from("Replaced"); + //~^ ERROR assigning to `&T` is undefined behavior + *(a as *const _ as *mut String) += " world"; + //~^ ERROR assigning to `&T` is undefined behavior + *std::ptr::from_ref(num).cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *std::ptr::from_ref({ num }).cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *{ std::ptr::from_ref(num) }.cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *(std::ptr::from_ref({ num }) as *mut i32) += 1; + //~^ ERROR assigning to `&T` is undefined behavior + let value = num as *const i32 as *mut i32; + *value = 1; + //~^ ERROR assigning to `&T` is undefined behavior } + +unsafe fn no_warn() { + let num = &3i32; + let mut_num = &mut 3i32; + let a = &String::from("ffi"); + + *(num as *const i32 as *mut i32); + println!("{}", *(num as *const _ as *const i16)); + println!("{}", *(mut_num as *mut _ as *mut i16)); + ffi(a.as_ptr() as *mut _); + int_ffi(num as *const _ as *mut _); + int_ffi(&3 as *const _ as *mut _); + let mut value = 3; + let value: *const i32 = &mut value; + *(value as *const i16 as *mut i16) = 42; +} + +fn main() {} diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 22bc66264d0..02b23600557 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -1,60 +1,92 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:19:9 + --> $DIR/reference_casting.rs:15:16 | -LL | *(a as *const _ as *mut _) = String::from("Replaced"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const i32 as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[deny(invalid_reference_casting)]` on by default error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:21:9 + --> $DIR/reference_casting.rs:17:16 | -LL | *(a as *const _ as *mut String) += " world"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const i32).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:23:20 + --> $DIR/reference_casting.rs:19:16 | -LL | let _num = &mut *(num as *const i32 as *mut i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *std::ptr::from_ref(num).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:25:20 + --> $DIR/reference_casting.rs:21:16 | -LL | let _num = &mut *(num as *const i32).cast_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:27:9 + --> $DIR/reference_casting.rs:23:16 | -LL | *std::ptr::from_ref(num).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:29:9 + --> $DIR/reference_casting.rs:25:16 | -LL | *std::ptr::from_ref({ num }).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:31:9 + --> $DIR/reference_casting.rs:29:16 | -LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let deferred = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +LL | let _num = &mut *deferred; + | ^^^^^^^^^^^^^^ -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:33:9 +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:38:5 | -LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | *(a as *const _ as *mut _) = String::from("Replaced"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:36:9 +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:40:5 | -LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here -LL | *value = 1; - | ^^^^^^^^^^ +LL | *(a as *const _ as *mut String) += " world"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:42:5 + | +LL | *std::ptr::from_ref(num).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:44:5 + | +LL | *std::ptr::from_ref({ num }).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:46:5 + | +LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:48:5 + | +LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:51:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +LL | *value = 1; + | ^^^^^^^^^^ + +error: aborting due to 14 previous errors From 507d497cfa014514c5dd904f9d273810e888f757 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 8 Jun 2023 21:36:20 +0200 Subject: [PATCH 07/19] Adjust some tests for invalid_reference_casting improvements --- library/core/src/cell.rs | 3 ++- src/tools/miri/tests/fail/both_borrows/illegal_write1.rs | 2 ++ src/tools/miri/tests/fail/stacked_borrows/illegal_write3.rs | 2 ++ tests/ui/const-generics/issues/issue-100313.rs | 2 +- tests/ui/const-generics/issues/issue-100313.stderr | 4 ++-- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 909b32547e7..bf4c682d33e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1893,7 +1893,8 @@ impl fmt::Display for RefMut<'_, T> { /// on an _exclusive_ `UnsafeCell`. Even though `T` and `UnsafeCell` have the /// same memory layout, the following is not allowed and undefined behavior: /// -/// ```rust,no_run +#[cfg_attr(bootstrap, doc = "```rust,no_run")] +#[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")] /// # use std::cell::UnsafeCell; /// unsafe fn not_allowed(ptr: &UnsafeCell) -> &mut T { /// let t = ptr as *const UnsafeCell as *mut T; diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write1.rs b/src/tools/miri/tests/fail/both_borrows/illegal_write1.rs index d3991949cc3..92f273f67bb 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write1.rs +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write1.rs @@ -1,6 +1,8 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows +#![allow(invalid_reference_casting)] + fn main() { let target = Box::new(42); // has an implicit raw let xref = &*target; diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.rs index 6f55b63cb5c..f79f7b561b8 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.rs @@ -1,3 +1,5 @@ +#![allow(invalid_reference_casting)] + fn main() { let target = 42; // Make sure raw ptr with raw tag cannot mutate frozen location without breaking the shared ref. diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs index 9a9d4721c84..9af9b5ca458 100644 --- a/tests/ui/const-generics/issues/issue-100313.rs +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -9,7 +9,7 @@ impl T { unsafe { *(B as *const bool as *mut bool) = false; //~^ ERROR evaluation of constant value failed [E0080] - //~| ERROR casting `&T` to `&mut T` is undefined behavior + //~| ERROR assigning to `&T` is undefined behavior } } } diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr index 17e4850bd12..42ad4d61c8e 100644 --- a/tests/ui/const-generics/issues/issue-100313.stderr +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -1,8 +1,8 @@ -error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/issue-100313.rs:10:13 | LL | *(B as *const bool as *mut bool) = false; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[deny(invalid_reference_casting)]` on by default From 7d5886504caacb3e9073d54aaf0b8ee8289ebc7f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Aug 2023 13:32:18 +0200 Subject: [PATCH 08/19] =?UTF-8?q?rename=20deref=5Foperand=20=E2=86=92=20de?= =?UTF-8?q?ref=5Fpointer=20and=20some=20Miri=20helper=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/const_eval/machine.rs | 4 +-- .../src/const_eval/valtrees.rs | 2 +- .../src/interpret/intrinsics.rs | 4 +-- .../rustc_const_eval/src/interpret/place.rs | 5 +-- .../src/interpret/projection.rs | 2 +- .../src/interpret/terminator.rs | 2 +- .../src/interpret/validity.rs | 4 +-- src/tools/miri/src/concurrency/sync.rs | 2 +- src/tools/miri/src/helpers.rs | 22 ++++++------ src/tools/miri/src/shims/backtrace.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 4 +-- src/tools/miri/src/shims/intrinsics/atomic.rs | 10 +++--- src/tools/miri/src/shims/intrinsics/mod.rs | 4 +-- src/tools/miri/src/shims/intrinsics/simd.rs | 4 +-- src/tools/miri/src/shims/time.rs | 14 ++++---- .../miri/src/shims/unix/foreign_items.rs | 16 ++++----- src/tools/miri/src/shims/unix/fs.rs | 10 +++--- src/tools/miri/src/shims/unix/linux/fd.rs | 4 +-- .../src/shims/unix/linux/foreign_items.rs | 2 +- .../src/shims/unix/macos/foreign_items.rs | 2 +- src/tools/miri/src/shims/unix/sync.rs | 34 +++++++++---------- src/tools/miri/src/shims/unix/thread.rs | 2 +- .../miri/src/shims/windows/foreign_items.rs | 10 +++--- src/tools/miri/src/shims/windows/sync.rs | 2 +- src/tools/miri/src/shims/windows/thread.rs | 2 +- 25 files changed, 84 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 6630eeca27e..032f4be6c99 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -214,9 +214,9 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // &str or &&str assert!(args.len() == 1); - let mut msg_place = self.deref_operand(&args[0])?; + let mut msg_place = self.deref_pointer(&args[0])?; while msg_place.layout.ty.is_ref() { - msg_place = self.deref_operand(&msg_place)?; + msg_place = self.deref_pointer(&msg_place)?; } let msg = Symbol::intern(self.read_str(&msg_place)?); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 7c1dbddfc26..f785bcfed6c 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -102,7 +102,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType), ty::Ref(_, _, _) => { - let Ok(derefd_place)= ecx.deref_operand(place) else { + let Ok(derefd_place)= ecx.deref_pointer(place) else { return Err(ValTreeCreationError::Other); }; debug!(?derefd_place); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index be7c14f33c2..29f3e6c724b 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -144,7 +144,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::min_align_of_val | sym::size_of_val => { - // Avoid `deref_operand` -- this is not a deref, the ptr does not have to be + // Avoid `deref_pointer` -- this is not a deref, the ptr does not have to be // dereferenceable! let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?; let (size, align) = self @@ -225,7 +225,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(val, dest)?; } sym::discriminant_value => { - let place = self.deref_operand(&args[0])?; + let place = self.deref_pointer(&args[0])?; let variant = self.read_discriminant(&place)?; let discr = self.discriminant_for_variant(place.layout, variant)?; self.write_scalar(discr, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 96a960118ce..5f4f5434b18 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -419,7 +419,7 @@ where /// /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not /// want to ever use the place for memory access! - /// Generally prefer `deref_operand`. + /// Generally prefer `deref_pointer`. pub fn ref_to_mplace( &self, val: &ImmTy<'tcx, M::Provenance>, @@ -439,8 +439,9 @@ where } /// Take an operand, representing a pointer, and dereference it to a place. + /// Corresponds to the `*` operator in Rust. #[instrument(skip(self), level = "debug")] - pub fn deref_operand( + pub fn deref_pointer( &self, src: &impl Readable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index bce43aedb69..539b58b7e9b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -290,7 +290,7 @@ where OpaqueCast(ty) => base.transmute(self.layout_of(ty)?, self)?, Field(field, _) => self.project_field(base, field.index())?, Downcast(_, variant) => self.project_downcast(base, variant)?, - Deref => self.deref_operand(&base.to_op(self)?)?.into(), + Deref => self.deref_pointer(&base.to_op(self)?)?.into(), Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; let n = self.local_to_op(self.frame(), local, Some(layout))?; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d0191ea978a..bf33c5cca10 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -661,7 +661,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let receiver_place = loop { match receiver.layout.ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { - // We do *not* use `deref_operand` here: we don't want to conceptually + // We do *not* use `deref_pointer` here: we don't want to conceptually // create a place that must be dereferenceable, since the receiver might // be a raw pointer and (for `*const dyn Trait`) we don't need to // actually access memory to resolve this method. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index aee95f70bc2..ff22d3d2d5a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -345,6 +345,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' value: &OpTy<'tcx, M::Provenance>, ptr_kind: PointerKind, ) -> InterpResult<'tcx> { + // Not using `deref_pointer` since we do the dereferenceable check ourselves below. let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?; // Handle wide pointers. // Check metadata early, for better diagnostics @@ -515,9 +516,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::RawPtr(..) => { - // We are conservative with uninit for integers, but try to - // actually enforce the strict rules for raw pointers (mostly because - // that lets us re-use `ref_to_mplace`). let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?; if place.layout.is_unsized() { diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index ec70b7042df..62f6d57ef36 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -206,7 +206,7 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>: ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); let value_place = - this.deref_operand_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; // Since we are lazy, this update has to be atomic. let (old, success) = this diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index d41bcc978b0..f9a8bad3a4f 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -715,9 +715,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type - fn deref_operand_as( + fn deref_pointer_as( &self, - op: &OpTy<'tcx, Provenance>, + op: &impl Readable<'tcx, Provenance>, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_ref(); @@ -746,15 +746,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Calculates the MPlaceTy given the offset and layout of an access on an operand - fn deref_operand_and_offset( + fn deref_pointer_and_offset( &self, - op: &OpTy<'tcx, Provenance>, + op: &impl Readable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_ref(); - let op_place = this.deref_operand_as(op, base_layout)?; + let op_place = this.deref_pointer_as(op, base_layout)?; let offset = Size::from_bytes(offset); // Ensure that the access is within bounds. @@ -763,28 +763,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(value_place) } - fn read_scalar_at_offset( + fn deref_pointer_and_read( &self, - op: &OpTy<'tcx, Provenance>, + op: &impl Readable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); - let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?; + let value_place = this.deref_pointer_and_offset(op, offset, base_layout, value_layout)?; this.read_scalar(&value_place) } - fn write_scalar_at_offset( + fn deref_pointer_and_write( &mut self, - op: &OpTy<'tcx, Provenance>, + op: &impl Readable<'tcx, Provenance>, offset: u64, value: impl Into>, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); - let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?; + let value_place = this.deref_pointer_and_offset(op, offset, base_layout, value_layout)?; this.write_scalar(value, &value_place) } diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 9f4bb37a469..a3297bf819f 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -97,7 +97,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { 1 => { let [_flags, buf] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let buf_place = this.deref_operand(buf)?; + let buf_place = this.deref_pointer(buf)?; let ptr_layout = this.layout_of(ptr_ty)?; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 763fa9235d0..167d1fd4518 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -418,9 +418,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // // First thing: load all the arguments. Details depend on the shim. // let arg1 = this.read_scalar(arg1)?.to_u32()?; // let arg2 = this.read_pointer(arg2)?; // when you need to work with the pointer directly - // let arg3 = this.deref_operand_as(arg3, this.libc_ty_layout("some_libc_struct"))?; // when you want to load/store + // let arg3 = this.deref_pointer_as(arg3, this.libc_ty_layout("some_libc_struct"))?; // when you want to load/store // // through the pointer and supply the type information yourself - // let arg4 = this.deref_operand(arg4)?; // when you want to load/store through the pointer and trust + // let arg4 = this.deref_pointer(arg4)?; // when you want to load/store through the pointer and trust // // the user-given type (which you shouldn't usually do) // // // ... diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 50f69bdca36..e38b677f485 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -130,7 +130,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let [place] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; // Perform atomic load. let val = this.read_scalar_atomic(&place, atomic)?; @@ -147,7 +147,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let [place, val] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; // Perform regular load. let val = this.read_scalar(val)?; @@ -188,7 +188,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let [place, rhs] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; let rhs = this.read_immediate(rhs)?; if !place.layout.ty.is_integral() && !place.layout.ty.is_unsafe_ptr() { @@ -229,7 +229,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let [place, new] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; let new = this.read_scalar(new)?; let old = this.atomic_exchange_scalar(&place, new, atomic)?; @@ -248,7 +248,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let [place, expect_old, new] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; let expect_old = this.read_immediate(expect_old)?; // read as immediate for the sake of `binary_op()` let new = this.read_scalar(new)?; diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 26f0a660657..c900ced19cd 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -96,12 +96,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Raw memory accesses "volatile_load" => { let [place] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; this.copy_op(&place, dest, /*allow_transmute*/ false)?; } "volatile_store" => { let [place, dest] = check_arg_count(args)?; - let place = this.deref_operand(place)?; + let place = this.deref_pointer(place)?; this.copy_op(dest, &place, /*allow_transmute*/ false)?; } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 103feae4ae7..b6225713cd0 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -534,7 +534,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; let val = if simd_element_to_bool(mask)? { - let place = this.deref_operand(&ptr)?; + let place = this.deref_pointer(&ptr)?; this.read_immediate(&place)? } else { passthru @@ -557,7 +557,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mask = this.read_immediate(&this.project_index(&mask, i)?)?; if simd_element_to_bool(mask)? { - let place = this.deref_operand(&ptr)?; + let place = this.deref_pointer(&ptr)?; this.write_immediate(*value, &place)?; } } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 935447fd89d..d6d0483f5e3 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -25,7 +25,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("clock_gettime"); let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; - let tp = this.deref_operand_as(tp_op, this.libc_ty_layout("timespec"))?; + let tp = this.deref_pointer_as(tp_op, this.libc_ty_layout("timespec"))?; let absolute_clocks; let mut relative_clocks; @@ -92,7 +92,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("gettimeofday"); this.check_no_isolation("`gettimeofday`")?; - let tv = this.deref_operand_as(tv_op, this.libc_ty_layout("timeval"))?; + let tv = this.deref_pointer_as(tv_op, this.libc_ty_layout("timeval"))?; // Using tz is obsolete and should always be null let tz = this.read_pointer(tz_op)?; @@ -121,7 +121,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("windows", "GetSystemTimeAsFileTime"); this.check_no_isolation("`GetSystemTimeAsFileTime`")?; - let filetime = this.deref_operand_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?; + let filetime = this.deref_pointer_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?; let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC"); let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC"); @@ -156,7 +156,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let qpc = i64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported") })?; - this.write_scalar(Scalar::from_i64(qpc), &this.deref_operand(lpPerformanceCount_op)?)?; + this.write_scalar(Scalar::from_i64(qpc), &this.deref_pointer(lpPerformanceCount_op)?)?; Ok(Scalar::from_i32(-1)) // return non-zero on success } @@ -176,7 +176,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and thus 10^9 counts per second. this.write_scalar( Scalar::from_i64(1_000_000_000), - &this.deref_operand_as(lpFrequency_op, this.machine.layouts.u64)?, + &this.deref_pointer_as(lpFrequency_op, this.machine.layouts.u64)?, )?; Ok(Scalar::from_i32(-1)) // Return non-zero on success } @@ -203,7 +203,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("macos", "mach_timebase_info"); - let info = this.deref_operand_as(info_op, this.libc_ty_layout("mach_timebase_info"))?; + let info = this.deref_pointer_as(info_op, this.libc_ty_layout("mach_timebase_info"))?; // Since our emulated ticks in `mach_absolute_time` *are* nanoseconds, // no scaling needs to happen. @@ -222,7 +222,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("nanosleep"); - let req = this.deref_operand_as(req_op, this.libc_ty_layout("timespec"))?; + let req = this.deref_pointer_as(req_op, this.libc_ty_layout("timespec"))?; let duration = match this.read_timespec(&req)? { Some(duration) => duration, diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 5f3c15c5874..3a480190535 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -191,7 +191,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Allocation "posix_memalign" => { let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let ret = this.deref_operand(ret)?; + let ret = this.deref_pointer(ret)?; let align = this.read_target_usize(align)?; let size = this.read_target_usize(size)?; // Align must be power of 2, and also at least ptr-sized (POSIX rules). @@ -271,7 +271,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Thread-local storage "pthread_key_create" => { let [key, dtor] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let key_place = this.deref_operand_as(key, this.libc_ty_layout("pthread_key_t"))?; + let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?; let dtor = this.read_pointer(dtor)?; // Extract the function type out of the signature (that seems easier than constructing it ourselves). @@ -506,7 +506,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_attr_getguardsize" if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let guard_size = this.deref_operand(guard_size)?; + let guard_size = this.deref_pointer(guard_size)?; let guard_size_layout = this.libc_ty_layout("size_t"); this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size)?; @@ -532,9 +532,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Hence we can mostly ignore the input `attr_place`. let [attr_place, addr_place, size_place] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let _attr_place = this.deref_operand_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?; - let addr_place = this.deref_operand(addr_place)?; - let size_place = this.deref_operand(size_place)?; + let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?; + let addr_place = this.deref_pointer(addr_place)?; + let size_place = this.deref_pointer(size_place)?; this.write_scalar( Scalar::from_uint(this.machine.stack_addr, this.pointer_size()), @@ -575,10 +575,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_no_isolation("`getpwuid_r`")?; let uid = this.read_scalar(uid)?.to_u32()?; - let pwd = this.deref_operand_as(pwd, this.libc_ty_layout("passwd"))?; + let pwd = this.deref_pointer_as(pwd, this.libc_ty_layout("passwd"))?; let buf = this.read_pointer(buf)?; let buflen = this.read_target_usize(buflen)?; - let result = this.deref_operand(result)?; + let result = this.deref_pointer(result)?; // Must be for "us". if uid != crate::shims::unix::UID { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index fe5b01e7610..09349bfdead 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -344,7 +344,7 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0)); let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0)); - let buf = this.deref_operand_as(buf_op, this.libc_ty_layout("stat"))?; + let buf = this.deref_pointer_as(buf_op, this.libc_ty_layout("stat"))?; this.write_int_fields_named( &[ @@ -1014,7 +1014,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(-1); } - let statxbuf = this.deref_operand_as(statxbuf_op, this.libc_ty_layout("statx"))?; + let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?; let path = this.read_path_from_c_str(pathname_ptr)?.into_owned(); // See for a discussion of argument sizes. @@ -1420,7 +1420,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // pub d_name: [c_char; 1024], // } - let entry_place = this.deref_operand_as(entry_op, this.libc_ty_layout("dirent"))?; + let entry_place = this.deref_pointer_as(entry_op, this.libc_ty_layout("dirent"))?; let name_place = this.project_field(&entry_place, 5)?; let file_name = dir_entry.file_name(); // not a Path as there are no separators! @@ -1456,14 +1456,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &entry_place, )?; - let result_place = this.deref_operand(result_op)?; + let result_place = this.deref_pointer(result_op)?; this.write_scalar(this.read_scalar(entry_op)?, &result_place)?; 0 } None => { // end of stream: return 0, assign *result=NULL - this.write_null(&this.deref_operand(result_op)?)?; + this.write_null(&this.deref_pointer(result_op)?)?; 0 } Some(Err(e)) => diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs index 92966319f19..f2be89ce637 100644 --- a/src/tools/miri/src/shims/unix/linux/fd.rs +++ b/src/tools/miri/src/shims/unix/linux/fd.rs @@ -71,7 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL"); if op == epoll_ctl_add || op == epoll_ctl_mod { - let event = this.deref_operand_as(event, this.libc_ty_layout("epoll_event"))?; + let event = this.deref_pointer_as(event, this.libc_ty_layout("epoll_event"))?; let events = this.project_field(&event, 0)?; let events = this.read_scalar(&events)?.to_u32()?; @@ -240,7 +240,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let _domain = this.read_scalar(domain)?.to_i32()?; let _type_ = this.read_scalar(type_)?.to_i32()?; let _protocol = this.read_scalar(protocol)?.to_i32()?; - let sv = this.deref_operand(sv)?; + let sv = this.deref_pointer(sv)?; let fh = &mut this.machine.file_handler; let sv0 = fh.insert_fd(Box::new(SocketPair)); diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index a97cc49d88e..1bd751c5981 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -198,7 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(pid)?.to_i32()?; this.read_target_usize(cpusetsize)?; - this.deref_operand_as(mask, this.libc_ty_layout("cpu_set_t"))?; + this.deref_pointer_as(mask, this.libc_ty_layout("cpu_set_t"))?; // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 5141b29b683..f073daab8ed 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -130,7 +130,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_no_isolation("`_NSGetExecutablePath`")?; let buf_ptr = this.read_pointer(buf)?; - let bufsize = this.deref_operand(bufsize)?; + let bufsize = this.deref_pointer(bufsize)?; // Using the host current_exe is a bit off, but consistent with Linux // (where stdlib reads /proc/self/exe). diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 0aeb8ae95a7..6666ffbd1d5 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -36,7 +36,7 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, attr_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset( + ecx.deref_pointer_and_read( attr_op, 0, ecx.libc_ty_layout("pthread_mutexattr_t"), @@ -50,7 +50,7 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>( attr_op: &OpTy<'tcx, Provenance>, kind: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( attr_op, 0, Scalar::from_i32(kind), @@ -79,7 +79,7 @@ fn mutex_reset_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, mutex_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( mutex_op, 4, Scalar::from_i32(0), @@ -93,7 +93,7 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>( mutex_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - ecx.read_scalar_at_offset( + ecx.deref_pointer_and_read( mutex_op, offset, ecx.libc_ty_layout("pthread_mutex_t"), @@ -108,7 +108,7 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>( kind: i32, ) -> InterpResult<'tcx, ()> { let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( mutex_op, offset, Scalar::from_i32(kind), @@ -141,7 +141,7 @@ fn condattr_get_clock_id<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, attr_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset( + ecx.deref_pointer_and_read( attr_op, 0, ecx.libc_ty_layout("pthread_condattr_t"), @@ -155,7 +155,7 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>( attr_op: &OpTy<'tcx, Provenance>, clock_id: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( attr_op, 0, Scalar::from_i32(clock_id), @@ -184,7 +184,7 @@ fn cond_reset_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, cond_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( cond_op, 4, Scalar::from_i32(0), @@ -197,7 +197,7 @@ fn cond_get_clock_id<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, cond_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset( + ecx.deref_pointer_and_read( cond_op, 8, ecx.libc_ty_layout("pthread_cond_t"), @@ -211,7 +211,7 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>( cond_op: &OpTy<'tcx, Provenance>, clock_id: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset( + ecx.deref_pointer_and_write( cond_op, 8, Scalar::from_i32(clock_id), @@ -346,7 +346,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // This can always be revisited to have some external state to catch double-destroys // but not complain about the above code. See https://github.com/rust-lang/miri/pull/1933 this.write_uninit( - &this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?, + &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?, )?; Ok(0) @@ -500,7 +500,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // This might lead to false positives, see comment in pthread_mutexattr_destroy this.write_uninit( - &this.deref_operand_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?, + &this.deref_pointer_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?, )?; // FIXME: delete interpreter state associated with this mutex. @@ -625,7 +625,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // This might lead to false positives, see comment in pthread_mutexattr_destroy this.write_uninit( - &this.deref_operand_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?, + &this.deref_pointer_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?, )?; // FIXME: delete interpreter state associated with this rwlock. @@ -675,7 +675,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let clock_id = condattr_get_clock_id(this, attr_op)?; - this.write_scalar(Scalar::from_i32(clock_id), &this.deref_operand(clk_id_op)?)?; + this.write_scalar(Scalar::from_i32(clock_id), &this.deref_pointer(clk_id_op)?)?; Ok(Scalar::from_i32(0)) } @@ -691,7 +691,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // This might lead to false positives, see comment in pthread_mutexattr_destroy this.write_uninit( - &this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?, + &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?, )?; Ok(0) @@ -784,7 +784,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Extract the timeout. let clock_id = cond_get_clock_id(this, cond_op)?; let duration = match this - .read_timespec(&this.deref_operand_as(abstime_op, this.libc_ty_layout("timespec"))?)? + .read_timespec(&this.deref_pointer_as(abstime_op, this.libc_ty_layout("timespec"))?)? { Some(duration) => duration, None => { @@ -867,7 +867,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { cond_get_clock_id(this, cond_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_operand_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?; + this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?; // FIXME: delete interpreter state associated with this condvar. Ok(0) diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 30ed110ca83..259689348ad 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -13,7 +13,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let thread_info_place = this.deref_operand_as(thread, this.libc_ty_layout("pthread_t"))?; + let thread_info_place = this.deref_pointer_as(thread, this.libc_ty_layout("pthread_t"))?; let start_routine = this.read_pointer(start_routine)?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 2f95cfb8bab..cb90ed57ffe 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -91,7 +91,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let n = this.read_scalar(n)?.to_u32()?; let byte_offset = this.read_target_usize(byte_offset)?; // is actually a pointer let io_status_block = this - .deref_operand_as(io_status_block, this.windows_ty_layout("IO_STATUS_BLOCK"))?; + .deref_pointer_as(io_status_block, this.windows_ty_layout("IO_STATUS_BLOCK"))?; if byte_offset != 0 { throw_unsup_format!( @@ -187,7 +187,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [system_info] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; let system_info = - this.deref_operand_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?; + this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?; // Initialize with `0`. this.write_bytes_ptr( system_info.ptr, @@ -391,8 +391,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [console, buffer_info] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(console)?; - // FIXME: this should use deref_operand_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std - this.deref_operand(buffer_info)?; + // FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std + this.deref_pointer(buffer_info)?; // Indicate an error. // FIXME: we should set last_error, but to what? this.write_null(dest)?; @@ -508,7 +508,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [console, mode] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(console)?; - this.deref_operand(mode)?; + this.deref_pointer(mode)?; // Indicate an error. this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 5d5cf73797f..c8c8173aa51 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let id = this.init_once_get_id(init_once_op)?; let flags = this.read_scalar(flags_op)?.to_u32()?; - let pending_place = this.deref_operand(pending_op)?.into(); + let pending_place = this.deref_pointer(pending_op)?.into(); let context = this.read_pointer(context_op)?; if flags != 0 { diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index 9cbae158859..3953a881a72 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -29,7 +29,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let thread = if this.ptr_is_null(this.read_pointer(thread_op)?)? { None } else { - let thread_info_place = this.deref_operand(thread_op)?; + let thread_info_place = this.deref_pointer(thread_op)?; Some(thread_info_place) }; From 8496292ddaec7696fa924d86cdea9ee26c1539b7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Aug 2023 17:03:19 +0200 Subject: [PATCH 09/19] properly track why we checked whether a pointer is in-bounds also simplify the in-bounds checking in Miri's borrow trackers --- compiler/rustc_const_eval/messages.ftl | 2 +- compiler/rustc_const_eval/src/errors.rs | 8 ++- .../rustc_const_eval/src/interpret/memory.rs | 23 ++++--- .../rustc_const_eval/src/interpret/step.rs | 3 +- .../rustc_middle/src/mir/interpret/error.rs | 4 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 16 +---- .../src/borrow_tracker/tree_borrows/mod.rs | 62 +++++++------------ .../miri/tests/fail/alloc/deallocate-twice.rs | 2 +- .../tests/fail/alloc/deallocate-twice.stderr | 4 +- .../fail/alloc/reallocate-change-alloc.rs | 2 +- .../fail/alloc/reallocate-change-alloc.stderr | 4 +- .../tests/fail/alloc/reallocate-dangling.rs | 2 +- .../fail/alloc/reallocate-dangling.stderr | 4 +- .../thread_local_static_dealloc.rs | 2 +- .../thread_local_static_dealloc.stderr | 4 +- .../dangling_pointer_addr_of.rs | 2 +- .../dangling_pointer_addr_of.stderr | 4 +- .../dangling_pointer_deref.rs | 2 +- .../dangling_pointer_deref.stderr | 4 +- .../dangling_pointer_offset.rs | 11 ++++ .../dangling_pointer_offset.stderr | 15 +++++ ...=> dangling_pointer_project_underscore.rs} | 2 +- ...angling_pointer_project_underscore.stderr} | 8 +-- .../dangling_pointers/dangling_zst_deref.rs | 2 +- .../dangling_zst_deref.stderr | 4 +- .../fail/dangling_pointers/stack_temporary.rs | 2 +- .../dangling_pointers/stack_temporary.stderr | 4 +- .../fail/data_race/dealloc_read_race2.rs | 2 +- .../fail/data_race/dealloc_read_race2.stderr | 4 +- .../fail/data_race/dealloc_write_race2.rs | 2 +- .../fail/data_race/dealloc_write_race2.stderr | 4 +- .../tests/fail/environ-gets-deallocated.rs | 2 +- .../fail/environ-gets-deallocated.stderr | 4 +- .../miri/tests/fail/generator-pinned-moved.rs | 2 +- .../tests/fail/generator-pinned-moved.stderr | 4 +- src/tools/miri/tests/fail/rc_as_ptr.rs | 2 +- src/tools/miri/tests/fail/rc_as_ptr.stderr | 4 +- .../tests/fail/shims/mmap_use_after_munmap.rs | 2 +- .../fail/shims/mmap_use_after_munmap.stderr | 4 +- src/tools/miri/tests/fail/zst2.rs | 2 +- src/tools/miri/tests/fail/zst2.stderr | 4 +- .../heap/dealloc_intrinsic_dangling.stderr | 4 +- .../heap/dealloc_intrinsic_duplicate.stderr | 2 +- tests/ui/consts/const-eval/issue-49296.stderr | 2 +- 44 files changed, 130 insertions(+), 122 deletions(-) create mode 100644 src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.rs create mode 100644 src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr rename src/tools/miri/tests/fail/dangling_pointers/{dangling_pointer_deref_underscore.rs => dangling_pointer_project_underscore.rs} (80%) rename src/tools/miri/tests/fail/dangling_pointers/{dangling_pointer_deref_underscore.stderr => dangling_pointer_project_underscore.stderr} (55%) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 671c2be1de9..2905874eec5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -282,7 +282,7 @@ const_eval_pointer_out_of_bounds = *[many] bytes } starting at offset {$ptr_offset} is out-of-bounds const_eval_pointer_use_after_free = - pointer to {$allocation} was dereferenced after this allocation got freed + {$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling const_eval_ptr_as_bytes_1 = this code performed an operation that depends on the underlying bytes representing a pointer const_eval_ptr_as_bytes_2 = diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index e1109e584b7..8cbc68d9061 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -492,7 +492,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, UnterminatedCString(_) => const_eval_unterminated_c_string, - PointerUseAfterFree(_) => const_eval_pointer_use_after_free, + PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free, PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds, PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds, DanglingIntPointer(0, _) => const_eval_dangling_null_pointer, @@ -545,8 +545,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { builder.set_arg("pointer", ptr); } - PointerUseAfterFree(allocation) => { - builder.set_arg("allocation", allocation); + PointerUseAfterFree(alloc_id, msg) => { + builder + .set_arg("alloc_id", alloc_id) + .set_arg("bad_pointer_message", bad_pointer_message(msg, handler)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { builder diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 02d022a2252..940a312d03b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -317,7 +317,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind = "static_mem" ) } - None => err_ub!(PointerUseAfterFree(alloc_id)), + None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccessTest)), } .into()); }; @@ -380,7 +380,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::enforce_alignment(self), CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, prov| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; + let (size, align) = self + .get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccessTest)?; Ok((size, align, (alloc_id, offset, prov))) }, ) @@ -404,7 +405,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { CheckAlignment::Error, msg, |alloc_id, _, _| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; + let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; Ok((size, align, ())) }, )?; @@ -414,7 +415,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference /// to the allocation it points to. Supports both shared and mutable references, as the actual /// checking is offloaded to a helper closure. `align` defines whether and which alignment check - /// is done. Returns `None` for size 0, and otherwise `Some` of what `alloc_size` returned. + /// is done. + /// + /// If this returns `None`, the size is 0; it can however return `Some` even for size 0. fn check_and_deref_ptr( &self, ptr: Pointer>, @@ -515,7 +518,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)), Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)), - None => throw_ub!(PointerUseAfterFree(id)), + None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccessTest)), Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); assert!(!self.tcx.is_thread_local_static(def_id)); @@ -761,11 +764,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - /// Obtain the size and alignment of a live allocation. - pub fn get_live_alloc_size_and_align(&self, id: AllocId) -> InterpResult<'tcx, (Size, Align)> { + /// Obtain the size and alignment of a *live* allocation. + fn get_live_alloc_size_and_align( + &self, + id: AllocId, + msg: CheckInAllocMsg, + ) -> InterpResult<'tcx, (Size, Align)> { let (size, align, kind) = self.get_alloc_info(id); if matches!(kind, AllocKind::Dead) { - throw_ub!(PointerUseAfterFree(id)) + throw_ub!(PointerUseAfterFree(id, msg)) } Ok((size, align)) } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 91341ddacd1..59285a339af 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -224,8 +224,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Len(place) => { let src = self.eval_place(place)?; - let op = self.place_to_op(&src)?; - let len = op.len(self)?; + let len = src.len(self)?; self.write_scalar(Scalar::from_target_usize(len, self), &dest)?; } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index d44dfa2172a..eaa6c0ce2d6 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -282,8 +282,8 @@ pub enum UndefinedBehaviorInfo<'a> { InvalidMeta(InvalidMetaKind), /// Reading a C string that does not end within its allocation. UnterminatedCString(Pointer), - /// Dereferencing a dangling pointer after it got freed. - PointerUseAfterFree(AllocId), + /// Using a pointer after it got freed. + PointerUseAfterFree(AllocId, CheckInAllocMsg), /// Used a pointer outside the bounds it is valid for. /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.) PointerOutOfBounds { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 8059fddb100..e929091b396 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{ layout::{HasParamEnv, LayoutOf}, Ty, }; -use rustc_target::abi::{Abi, Size}; +use rustc_target::abi::{Abi, Align, Size}; use crate::borrow_tracker::{ stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder}, @@ -619,6 +619,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' retag_info: RetagInfo, // diagnostics info about this retag ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); + // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). + this.check_ptr_access_align(place.ptr, size, Align::ONE, CheckInAllocMsg::InboundsTest)?; // It is crucial that this gets called on all code paths, to ensure we track tag creation. let log_creation = |this: &MiriInterpCx<'mir, 'tcx>, @@ -707,18 +709,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?; log_creation(this, Some((alloc_id, base_offset, orig_tag)))?; - // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). - let (alloc_size, _) = this.get_live_alloc_size_and_align(alloc_id)?; - if base_offset + size > alloc_size { - throw_ub!(PointerOutOfBounds { - alloc_id, - alloc_size, - ptr_offset: this.target_usize_to_isize(base_offset.bytes()), - ptr_size: size, - msg: CheckInAllocMsg::InboundsTest - }); - } - trace!( "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}", new_tag, diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 9073f695442..b2dbe8a70f0 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,6 +1,6 @@ use log::trace; -use rustc_target::abi::{Abi, Size}; +use rustc_target::abi::{Abi, Align, Size}; use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind, RetagFields}; use rustc_middle::{ @@ -182,6 +182,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' new_tag: BorTag, ) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> { let this = self.eval_context_mut(); + // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). + this.check_ptr_access_align(place.ptr, ptr_size, Align::ONE, CheckInAllocMsg::InboundsTest)?; // It is crucial that this gets called on all code paths, to ensure we track tag creation. let log_creation = |this: &MiriInterpCx<'mir, 'tcx>, @@ -202,51 +204,33 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' }; trace!("Reborrow of size {:?}", ptr_size); - let (alloc_id, base_offset, parent_prov) = if ptr_size > Size::ZERO { - this.ptr_get_alloc_id(place.ptr)? - } else { - match this.ptr_try_get_alloc_id(place.ptr) { - Ok(data) => data, - Err(_) => { - // This pointer doesn't come with an AllocId, so there's no - // memory to do retagging in. - trace!( - "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", - new_tag, - place.ptr, - place.layout.ty, - ); - log_creation(this, None)?; - return Ok(None); - } + let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr) { + Ok(data) => { + // Unlike SB, we *do* a proper retag for size 0 if can identify the allocation. + // After all, the pointer may be lazily initialized outside this initial range. + data + }, + Err(_) => { + assert_eq!(ptr_size, Size::ZERO); // we did the deref check above, size has to be 0 here + // This pointer doesn't come with an AllocId, so there's no + // memory to do retagging in. + trace!( + "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", + new_tag, + place.ptr, + place.layout.ty, + ); + log_creation(this, None)?; + return Ok(None); } }; + log_creation(this, Some((alloc_id, base_offset, parent_prov)))?; + let orig_tag = match parent_prov { ProvenanceExtra::Wildcard => return Ok(None), // TODO: handle wildcard pointers ProvenanceExtra::Concrete(tag) => tag, }; - // Protection against trying to get a reference to a vtable: - // vtables do not have an alloc_extra so the call to - // `get_alloc_extra` that follows fails. - let (alloc_size, _align, alloc_kind) = this.get_alloc_info(alloc_id); - if ptr_size == Size::ZERO && !matches!(alloc_kind, AllocKind::LiveData) { - return Ok(Some((alloc_id, orig_tag))); - } - - log_creation(this, Some((alloc_id, base_offset, parent_prov)))?; - - // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050). - if base_offset + ptr_size > alloc_size { - throw_ub!(PointerOutOfBounds { - alloc_id, - alloc_size, - ptr_offset: this.target_usize_to_isize(base_offset.bytes()), - ptr_size, - msg: CheckInAllocMsg::InboundsTest - }); - } - trace!( "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}", new_tag, diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.rs b/src/tools/miri/tests/fail/alloc/deallocate-twice.rs index f07bbda4a9b..7a3ff84b2cb 100644 --- a/src/tools/miri/tests/fail/alloc/deallocate-twice.rs +++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.rs @@ -1,6 +1,6 @@ use std::alloc::{alloc, dealloc, Layout}; -//@error-in-other-file: dereferenced after this allocation got freed +//@error-in-other-file: has been freed fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr index fa7a74ee13c..23d145e7d30 100644 --- a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr +++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling --> RUSTLIB/alloc/src/alloc.rs:LL:CC | LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.rs b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.rs index 3ad56da2c2f..ecdd3ae5fee 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.rs +++ b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.rs @@ -4,6 +4,6 @@ fn main() { unsafe { let x = alloc(Layout::from_size_align_unchecked(1, 1)); let _y = realloc(x, Layout::from_size_align_unchecked(1, 1), 1); - let _z = *x; //~ ERROR: dereferenced after this allocation got freed + let _z = *x; //~ ERROR: has been freed } } diff --git a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr index 5631dcb4cc0..7c7cec211b7 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr +++ b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/reallocate-change-alloc.rs:LL:CC | LL | let _z = *x; - | ^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs b/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs index 130e2a8301e..622348ad190 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs +++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.rs @@ -1,6 +1,6 @@ use std::alloc::{alloc, dealloc, realloc, Layout}; -//@error-in-other-file: dereferenced after this allocation got freed +//@error-in-other-file: has been freed fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr index b1460bfb763..9c222154716 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr +++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling --> RUSTLIB/alloc/src/alloc.rs:LL:CC | LL | unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs b/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs index d89c670b632..d5e6d37226a 100644 --- a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs +++ b/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs @@ -11,6 +11,6 @@ unsafe impl Send for SendRaw {} fn main() { unsafe { let dangling_ptr = std::thread::spawn(|| SendRaw(&TLS as *const u8)).join().unwrap(); - let _val = *dangling_ptr.0; //~ ERROR: dereferenced after this allocation got freed + let _val = *dangling_ptr.0; //~ ERROR: has been freed } } diff --git a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr b/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr index cc3e5639878..0cb8aa29001 100644 --- a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr +++ b/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/thread_local_static_dealloc.rs:LL:CC | LL | let _val = *dangling_ptr.0; - | ^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.rs index 4249c1cbf01..49f3ae306a0 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.rs @@ -7,6 +7,6 @@ fn main() { let b = Box::new(42); &*b as *const i32 }; - let x = unsafe { ptr::addr_of!(*p) }; //~ ERROR: dereferenced after this allocation got freed + let x = unsafe { ptr::addr_of!(*p) }; //~ ERROR: has been freed panic!("this should never print: {:?}", x); } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr index 5f081afe68a..398f216e731 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/dangling_pointer_addr_of.rs:LL:CC | LL | let x = unsafe { ptr::addr_of!(*p) }; - | ^^^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.rs index ad2a599b60b..675e3e15da8 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.rs @@ -6,6 +6,6 @@ fn main() { let b = Box::new(42); &*b as *const i32 }; - let x = unsafe { *p }; //~ ERROR: dereferenced after this allocation got freed + let x = unsafe { *p }; //~ ERROR: has been freed panic!("this should never print: {}", x); } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr index cb323818845..cb95d71a605 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/dangling_pointer_deref.rs:LL:CC | LL | let x = unsafe { *p }; - | ^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.rs new file mode 100644 index 00000000000..65eca07a070 --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.rs @@ -0,0 +1,11 @@ +// Make sure we find these even with many checks disabled. +//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation + +fn main() { + let p = { + let b = Box::new(42); + &*b as *const i32 + }; + let x = unsafe { p.offset(42) }; //~ ERROR: /out-of-bounds pointer arithmetic: .* has been freed/ + panic!("this should never print: {:?}", x); +} diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr new file mode 100644 index 00000000000..85bd2bed9c3 --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling + --> $DIR/dangling_pointer_offset.rs:LL:CC + | +LL | let x = unsafe { p.offset(42) }; + | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/dangling_pointer_offset.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs similarity index 80% rename from src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs rename to src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs index 7c5f440b774..4c641243950 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.rs @@ -7,7 +7,7 @@ fn main() { &*b as *const i32 }; unsafe { - let _ = *p; //~ ERROR: dereferenced after this allocation got freed + let _ = *p; //~ ERROR: has been freed } panic!("this should never print"); } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr similarity index 55% rename from src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr rename to src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr index 7b76389c753..f2d58fe7697 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr @@ -1,13 +1,13 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed - --> $DIR/dangling_pointer_deref_underscore.rs:LL:CC +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling + --> $DIR/dangling_pointer_project_underscore.rs:LL:CC | LL | let _ = *p; - | ^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/dangling_pointer_deref_underscore.rs:LL:CC + = note: inside `main` at $DIR/dangling_pointer_project_underscore.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.rs index e749eb896e2..a1fefe04ab6 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.rs @@ -6,5 +6,5 @@ fn main() { let b = Box::new(42); &*b as *const i32 as *const () }; - let _x = unsafe { *p }; //~ ERROR: dereferenced after this allocation got freed + let _x = unsafe { *p }; //~ ERROR: has been freed } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr index 02db6302a0a..c15f17f3b82 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/dangling_zst_deref.rs:LL:CC | LL | let _x = unsafe { *p }; - | ^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.rs b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.rs index c193d5fe0b3..5f8a1988b3c 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.rs @@ -8,7 +8,7 @@ unsafe fn make_ref<'a>(x: *mut i32) -> &'a mut i32 { fn main() { unsafe { let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"! - let val = *x; //~ ERROR: dereferenced after this allocation got freed + let val = *x; //~ ERROR: has been freed println!("{}", val); } } diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr index 679e4809ca6..500f28a3cbc 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/stack_temporary.rs:LL:CC | LL | let val = *x; - | ^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs index 5d7a0cc1dc9..c921ce6b716 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs @@ -32,7 +32,7 @@ pub fn main() { let ptr = ptr; // avoid field capturing // Also an error of the form: Data race detected between (1) Deallocate on thread `` and (2) Read on thread `` // but the invalid allocation is detected first. - *ptr.0 //~ ERROR: dereferenced after this allocation got freed + *ptr.0 //~ ERROR: has been freed }); j1.join().unwrap(); diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr index f303d57c8bd..4efc35c15e2 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/dealloc_read_race2.rs:LL:CC | LL | *ptr.0 - | ^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs index a7f43f03c02..e01132202d4 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs @@ -31,7 +31,7 @@ pub fn main() { let ptr = ptr; // avoid field capturing // Also an error of the form: Data race detected between (1) Deallocate on thread `` and (2) Write on thread `` // but the invalid allocation is detected first. - *ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed + *ptr.0 = 2; //~ ERROR: has been freed }); j1.join().unwrap(); diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr index 23b8e9ade0e..fad525830e6 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/dealloc_write_race2.rs:LL:CC | LL | *ptr.0 = 2; - | ^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/environ-gets-deallocated.rs b/src/tools/miri/tests/fail/environ-gets-deallocated.rs index e4597140b84..6dcf1fdb1c7 100644 --- a/src/tools/miri/tests/fail/environ-gets-deallocated.rs +++ b/src/tools/miri/tests/fail/environ-gets-deallocated.rs @@ -20,5 +20,5 @@ fn main() { let pointer = get_environ(); let _x = unsafe { *pointer }; std::env::set_var("FOO", "BAR"); - let _y = unsafe { *pointer }; //~ ERROR: dereferenced after this allocation got freed + let _y = unsafe { *pointer }; //~ ERROR: has been freed } diff --git a/src/tools/miri/tests/fail/environ-gets-deallocated.stderr b/src/tools/miri/tests/fail/environ-gets-deallocated.stderr index a2d343bf865..6332846d5d8 100644 --- a/src/tools/miri/tests/fail/environ-gets-deallocated.stderr +++ b/src/tools/miri/tests/fail/environ-gets-deallocated.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/environ-gets-deallocated.rs:LL:CC | LL | let _y = unsafe { *pointer }; - | ^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.rs b/src/tools/miri/tests/fail/generator-pinned-moved.rs index 29dc6e56f7c..33348ace9c4 100644 --- a/src/tools/miri/tests/fail/generator-pinned-moved.rs +++ b/src/tools/miri/tests/fail/generator-pinned-moved.rs @@ -13,7 +13,7 @@ fn firstn() -> impl Generator { *num += 0; yield *num; - *num += 1; //~ERROR: dereferenced after this allocation got freed + *num += 1; //~ERROR: has been freed } } diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.stderr b/src/tools/miri/tests/fail/generator-pinned-moved.stderr index 80c5794736a..3eb17f05584 100644 --- a/src/tools/miri/tests/fail/generator-pinned-moved.stderr +++ b/src/tools/miri/tests/fail/generator-pinned-moved.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/generator-pinned-moved.rs:LL:CC | LL | *num += 1; - | ^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/rc_as_ptr.rs b/src/tools/miri/tests/fail/rc_as_ptr.rs index 6aea1870748..ebcf49b8f99 100644 --- a/src/tools/miri/tests/fail/rc_as_ptr.rs +++ b/src/tools/miri/tests/fail/rc_as_ptr.rs @@ -16,5 +16,5 @@ fn main() { drop(strong); // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to // undefined behaviour. - assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) }); //~ ERROR: dereferenced after this allocation got freed + assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) }); //~ ERROR: has been freed } diff --git a/src/tools/miri/tests/fail/rc_as_ptr.stderr b/src/tools/miri/tests/fail/rc_as_ptr.stderr index 70bdd157bdc..129916ac73c 100644 --- a/src/tools/miri/tests/fail/rc_as_ptr.stderr +++ b/src/tools/miri/tests/fail/rc_as_ptr.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/rc_as_ptr.rs:LL:CC | LL | assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs index 1e00bc6b64f..c97b013ba5a 100644 --- a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs +++ b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.rs @@ -14,6 +14,6 @@ fn main() { 0, ); libc::munmap(ptr, 4096); - let _x = *(ptr as *mut u8); //~ ERROR: was dereferenced after this allocation got freed + let _x = *(ptr as *mut u8); //~ ERROR: has been freed } } diff --git a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr index f90701d400c..8b9969da8fd 100644 --- a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr +++ b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr @@ -13,11 +13,11 @@ LL | libc::munmap(ptr, 4096); = note: BACKTRACE: = note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/mmap_use_after_munmap.rs:LL:CC | LL | let _x = *(ptr as *mut u8); - | ^^^^^^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/zst2.rs b/src/tools/miri/tests/fail/zst2.rs index 1d3e8ea9d00..04218c264a3 100644 --- a/src/tools/miri/tests/fail/zst2.rs +++ b/src/tools/miri/tests/fail/zst2.rs @@ -8,5 +8,5 @@ fn main() { let mut x_box = Box::new(1u8); let x = &mut *x_box as *mut _ as *mut [u8; 0]; drop(x_box); - unsafe { *x = zst_val }; //~ ERROR: dereferenced after this allocation got freed + unsafe { *x = zst_val }; //~ ERROR: has been freed } diff --git a/src/tools/miri/tests/fail/zst2.stderr b/src/tools/miri/tests/fail/zst2.stderr index 6c49656e4c6..63f40ed2067 100644 --- a/src/tools/miri/tests/fail/zst2.stderr +++ b/src/tools/miri/tests/fail/zst2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling --> $DIR/zst2.rs:LL:CC | LL | unsafe { *x = zst_val }; - | ^^^^^^^^^^^^ pointer to ALLOC was dereferenced after this allocation got freed + | ^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr index 4eb1c42e1f7..b50ef0c68a1 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_dangling.rs:10:5 | LL | &*ptr - | ^^^^^ pointer to alloc2 was dereferenced after this allocation got freed + | ^^^^^ dereferencing pointer failed: alloc2 has been freed, so this pointer is dangling error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_dangling.rs:18:5 | LL | *reference - | ^^^^^^^^^^ pointer to alloc4 was dereferenced after this allocation got freed + | ^^^^^^^^^^ dereferencing pointer failed: alloc4 has been freed, so this pointer is dangling error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr index 8177a08504b..0884ade45a7 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/dealloc_intrinsic_duplicate.rs:9:5 | LL | intrinsics::const_deallocate(ptr, 4, 4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc2 has been freed, so this pointer is dangling error: aborting due to previous error diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index cc4f1594c32..45ba0ea183e 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-49296.rs:9:16 | LL | const X: u64 = *wat(42); - | ^^^^^^^^ pointer to alloc3 was dereferenced after this allocation got freed + | ^^^^^^^^ dereferencing pointer failed: alloc3 has been freed, so this pointer is dangling error: aborting due to previous error From 69b02ef4be1004847544c89e6299b2e41b5d275f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Aug 2023 18:22:33 +0200 Subject: [PATCH 10/19] fix and extend ptr_comparison test --- tests/ui/consts/ptr_comparisons.rs | 36 ++++++----------------- tests/ui/consts/ptr_comparisons.stderr | 40 -------------------------- 2 files changed, 8 insertions(+), 68 deletions(-) delete mode 100644 tests/ui/consts/ptr_comparisons.stderr diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs index f442e613839..a5b6cd9d2d4 100644 --- a/tests/ui/consts/ptr_comparisons.rs +++ b/tests/ui/consts/ptr_comparisons.rs @@ -1,8 +1,5 @@ // compile-flags: --crate-type=lib -// normalize-stderr-32bit: "8 bytes" -> "$$TWO_WORDS bytes" -// normalize-stderr-64bit: "16 bytes" -> "$$TWO_WORDS bytes" -// normalize-stderr-32bit: "size 4" -> "size $$WORD" -// normalize-stderr-64bit: "size 8" -> "size $$WORD" +// check-pass #![feature( core_intrinsics, @@ -34,30 +31,13 @@ check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0); // We want pointers to be equal to themselves, but aren't checking this yet because // there are some open questions (e.g. whether function pointers to the same function -// compare equal, they don't necessarily at runtime). -// The case tested here should work eventually, but does not work yet. +// compare equal: they don't necessarily do at runtime). check!(!, FOO as *const _, FOO as *const _); +// aside from 0, these pointers might end up pretty much anywhere. +check!(!, FOO as *const _, 1); // this one could be `ne` by taking into account alignment +check!(!, FOO as *const _, 1024); -/////////////////////////////////////////////////////////////////////////////// -// If any of the below start compiling, make sure to add a `check` test for it. -// These invocations exist as canaries so we don't forget to check that the -// behaviour of `guaranteed_eq` and `guaranteed_ne` is still correct. -// All of these try to obtain an out of bounds pointer in some manner. If we -// can create out of bounds pointers, we can offset a pointer far enough that -// at runtime it would be zero and at compile-time it would not be zero. - -const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - -const _: *const u8 = - unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; -//~^ ERROR evaluation of constant value failed -//~| out-of-bounds - -const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; -//~^ ERROR evaluation of constant value failed -//~| unable to turn pointer into raw bytes - -const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; -//~^ ERROR evaluation of constant value failed -//~| unable to turn pointer into raw bytes +// When pointers go out-of-bounds, they *might* become null, so these comparions cannot work. +check!(!, unsafe { (FOO as *const usize).wrapping_add(2) }, 0); +check!(!, unsafe { (FOO as *const usize).wrapping_sub(1) }, 0); diff --git a/tests/ui/consts/ptr_comparisons.stderr b/tests/ui/consts/ptr_comparisons.stderr deleted file mode 100644 index fea924d12e5..00000000000 --- a/tests/ui/consts/ptr_comparisons.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - | - = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds - | -note: inside `ptr::const_ptr::::offset` - --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL -note: inside `_` - --> $DIR/ptr_comparisons.rs:50:34 - | -LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:53:33 - | -LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:57:27 - | -LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes - | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported - -error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:61:27 - | -LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes - | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0080`. From 7c12b2e6367713a00623780a50cf08a5edb3427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 1 Aug 2023 21:45:20 +0000 Subject: [PATCH 11/19] Revert "Rollup merge of #113588 - RalfJung:llvm-merge-base, r=albertlarsan68" This reverts commit 849f4f8845ad3104596244874d9e8a087ca2e15b, reversing changes made to 02426434e2ff0194e41dcd8420e9c87346149985. --- src/bootstrap/llvm.rs | 9 +------- src/tools/build_helper/src/git.rs | 38 +++++++++++++++---------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index d8718d26848..81b88d5de98 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -24,7 +24,6 @@ use crate::util::{self, exe, output, t, up_to_date}; use crate::{CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; -use build_helper::git::get_git_merge_base; #[derive(Clone)] pub struct LlvmResult { @@ -129,19 +128,13 @@ pub fn prebuilt_llvm_config( /// This retrieves the LLVM sha we *want* to use, according to git history. pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { let llvm_sha = if is_git { - // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we - // walk back further to the last bors merge commit that actually changed LLVM. The first - // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` - // in that case. - let closest_upstream = - get_git_merge_base(Some(&config.src)).unwrap_or_else(|_| "HEAD".into()); let mut rev_list = config.git(); rev_list.args(&[ PathBuf::from("rev-list"), format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(), "-n1".into(), "--first-parent".into(), - closest_upstream.into(), + "HEAD".into(), "--".into(), config.src.join("src/llvm-project"), config.src.join("src/bootstrap/download-ci-llvm-stamp"), diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index f20b7a2b4d7..66876e02c19 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -78,22 +78,13 @@ pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result { /// We will then fall back to origin/master in the hope that at least this exists. pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { let upstream_remote = get_rust_lang_rust_remote(git_dir)?; - for upstream_master in [format!("{upstream_remote}/master"), format!("origin/master")] { - if rev_exists(&upstream_master, git_dir)? { - return Ok(upstream_master); - } + let upstream_master = format!("{upstream_remote}/master"); + if rev_exists(&upstream_master, git_dir)? { + return Ok(upstream_master); } - Err(format!("Cannot find any suitable upstream master branch")) -} - -pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { - let updated_master = updated_master_branch(git_dir)?; - let mut git = Command::new("git"); - if let Some(git_dir) = git_dir { - git.current_dir(git_dir); - } - Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) + // We could implement smarter logic here in the future. + Ok("origin/master".into()) } /// Returns the files that have been modified in the current branch compared to the master branch. @@ -103,13 +94,20 @@ pub fn get_git_modified_files( git_dir: Option<&Path>, extensions: &Vec<&str>, ) -> Result>, String> { - let merge_base = get_git_merge_base(git_dir)?; + let Ok(updated_master) = updated_master_branch(git_dir) else { + return Ok(None); + }; - let mut git = Command::new("git"); - if let Some(git_dir) = git_dir { - git.current_dir(git_dir); - } - let files = output_result(git.args(["diff-index", "--name-only", merge_base.trim()]))? + let git = || { + let mut git = Command::new("git"); + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + git + }; + + let merge_base = output_result(git().arg("merge-base").arg(&updated_master).arg("HEAD"))?; + let files = output_result(git().arg("diff-index").arg("--name-only").arg(merge_base.trim()))? .lines() .map(|s| s.trim().to_owned()) .filter(|f| { From 79709e5d1afdbf9f446378541fa7b9f83ea3f144 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 31 Jul 2023 15:06:56 +0800 Subject: [PATCH 12/19] print more detailed format files and untracked files count --- src/bootstrap/format.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 3f9230aa5d5..6d11014a794 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -152,6 +152,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { .map(|entry| { entry.split(' ').nth(1).expect("every git status entry should list a path") }); + let mut untracked_count = 0; for untracked_path in untracked_paths { println!("skip untracked path {untracked_path} during rustfmt invocations"); // The leading `/` makes it an exact match against the @@ -159,6 +160,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // have `foo.rs` in the repository root it will also match // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. + untracked_count += 1; ignore_fmt.add(&format!("!/{untracked_path}")).expect(&untracked_path); } // Only check modified files locally to speed up runtime. @@ -167,13 +169,28 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { if !CiEnv::is_ci() && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { + eprintln!("Found {:?} modified files", files); if files.len() <= 10 { for file in &files { println!("formatting modified file {file}"); } - } else { - println!("formatting {} modified files", files.len()); } + let pluralized = |count| if count > 1 { "files" } else { "file" }; + let untracked_msg = if untracked_count == 0 { + "".to_string() + } else { + format!( + ", skipped {} untracked {}", + untracked_count, + pluralized(untracked_count), + ) + }; + println!( + "formatting {} modified {}{}", + files.len(), + pluralized(files.len()), + untracked_msg + ); for file in files { ignore_fmt.add(&format!("/{file}")).expect(&file); } From 58bda4766964f93add4d03d95f0223460cf875bd Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 2 Aug 2023 06:29:32 +0800 Subject: [PATCH 13/19] fmt_override is a better name since we are also adding files to whitelist --- src/bootstrap/format.rs | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6d11014a794..d658be0b8eb 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -113,9 +113,9 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config)); let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config)); - let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src); + let mut fmt_override = ignore::overrides::OverrideBuilder::new(&build.src); for ignore in rustfmt_config.ignore { - ignore_fmt.add(&format!("!{ignore}")).expect(&ignore); + fmt_override.add(&format!("!{ignore}")).expect(&ignore); } let git_available = match Command::new("git") .arg("--version") @@ -161,7 +161,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // against anything like `compiler/rustc_foo/src/foo.rs`, // preventing the latter from being formatted. untracked_count += 1; - ignore_fmt.add(&format!("!/{untracked_path}")).expect(&untracked_path); + fmt_override.add(&format!("!/{untracked_path}")).expect(&untracked_path); } // Only check modified files locally to speed up runtime. // We still check all files in CI to avoid bugs in `get_modified_rs_files` letting regressions slip through; @@ -169,30 +169,30 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { if !CiEnv::is_ci() && paths.is_empty() { match get_modified_rs_files(build) { Ok(Some(files)) => { - eprintln!("Found {:?} modified files", files); if files.len() <= 10 { for file in &files { println!("formatting modified file {file}"); } - } - let pluralized = |count| if count > 1 { "files" } else { "file" }; - let untracked_msg = if untracked_count == 0 { - "".to_string() } else { - format!( - ", skipped {} untracked {}", - untracked_count, - pluralized(untracked_count), - ) - }; - println!( - "formatting {} modified {}{}", - files.len(), - pluralized(files.len()), - untracked_msg - ); + let pluralized = |count| if count > 1 { "files" } else { "file" }; + let untracked_msg = if untracked_count == 0 { + "".to_string() + } else { + format!( + ", skipped {} untracked {}", + untracked_count, + pluralized(untracked_count), + ) + }; + println!( + "formatting {} modified {}{}", + files.len(), + pluralized(files.len()), + untracked_msg + ); + } for file in files { - ignore_fmt.add(&format!("/{file}")).expect(&file); + fmt_override.add(&format!("/{file}")).expect(&file); } } Ok(None) => {} @@ -213,7 +213,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { println!("Could not find usable git. Skipping git-aware format checks"); } - let ignore_fmt = ignore_fmt.build().unwrap(); + let fmt_override = fmt_override.build().unwrap(); let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { eprintln!("./x.py fmt is not supported on this channel"); @@ -269,7 +269,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { None => WalkBuilder::new(src.clone()), } .types(matcher) - .overrides(ignore_fmt) + .overrides(fmt_override) .build_parallel(); // there is a lot of blocking involved in spawning a child process and reading files to format. From 99969d282bd853442d7539b83833816b73e642e1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Jul 2023 23:31:21 +0000 Subject: [PATCH 14/19] Use upvar_tys in more places, make it a list --- .../src/diagnostics/region_name.rs | 1 + .../src/diagnostics/var_name.rs | 4 +-- compiler/rustc_borrowck/src/type_check/mod.rs | 27 ++++++++----------- .../rustc_borrowck/src/universal_regions.rs | 11 +++----- .../src/debuginfo/metadata.rs | 14 +++------- .../src/debuginfo/metadata/enums/mod.rs | 1 + .../src/transform/validate.rs | 5 ++-- .../rustc_infer/src/infer/opaque_types.rs | 8 ++++-- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +-- compiler/rustc_middle/src/ty/sty.rs | 26 +++++++----------- .../rustc_mir_dataflow/src/elaborate_drops.rs | 10 ++----- compiler/rustc_mir_transform/src/generator.rs | 4 +-- .../src/traits/query/dropck_outlives.rs | 6 ++--- .../src/traits/select/mod.rs | 5 ++-- compiler/rustc_ty_utils/src/layout.rs | 8 ++++-- compiler/rustc_ty_utils/src/needs_drop.rs | 8 ++++-- 17 files changed, 66 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9cad8fa5318..be6eb2d1d12 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -886,6 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .universal_regions() .defining_ty .upvar_tys() + .iter() .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region)) { let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 98418e2372f..8832d345df2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -43,7 +43,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option { let upvar_index = - self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys().iter().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.as_var(); @@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index); debug!( "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}", diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fd4a3ec1a5e..abb11ce7396 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -791,25 +791,20 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { (adt_def.variant(FIRST_VARIANT), args) } ty::Closure(_, args) => { - return match args - .as_closure() - .tupled_upvars_ty() - .tuple_fields() - .get(field.index()) - { + return match args.as_closure().upvar_tys().get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), }; } ty::Generator(_, args, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match args.as_generator().prefix_tys().nth(field.index()) { - Some(ty) => Ok(ty), + return match args.as_generator().prefix_tys().get(field.index()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), }; } @@ -1772,10 +1767,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } AggregateKind::Closure(_, args) => { - match args.as_closure().upvar_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), } } @@ -1783,10 +1778,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match args.as_generator().prefix_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_generator().prefix_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index a751a9732f0..56945f43fcd 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,7 +12,6 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir as hir; @@ -115,14 +114,12 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or generator, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx ty::List> { match self { - DefiningTy::Closure(_, args) => Either::Left(args.as_closure().upvar_tys()), - DefiningTy::Generator(_, args, _) => { - Either::Right(Either::Left(args.as_generator().upvar_tys())) - } + DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - Either::Right(Either::Right(iter::empty())) + ty::List::empty() } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 40f0bcfdf58..f8cbcbd5ec8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -990,14 +990,8 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( closure_or_generator_di_node: &'ll DIType, ) -> SmallVec<&'ll DIType> { let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() { - ty::Generator(def_id, args, _) => { - let upvar_tys: SmallVec<_> = args.as_generator().prefix_tys().collect(); - (def_id, upvar_tys) - } - ty::Closure(def_id, args) => { - let upvar_tys: SmallVec<_> = args.as_closure().upvar_tys().collect(); - (def_id, upvar_tys) - } + ty::Generator(def_id, args, _) => (def_id, args.as_generator().prefix_tys()), + ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}", @@ -1007,9 +1001,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( }; debug_assert!( - up_var_tys - .iter() - .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) + up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) ); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index b4beb80ca8b..d3239d5c358 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -379,6 +379,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( // Fields that are common to all states let common_fields: SmallVec<_> = generator_args .prefix_tys() + .iter() .zip(common_upvar_names) .enumerate() .map(|(index, (upvar_ty, upvar_name))| { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 31effadd2c2..83004492c8b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } ty::Closure(_, args) => { let args = args.as_closure(); - let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else { + let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else { fail_out_of_bounds(self, location); return; }; @@ -667,7 +667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { f_ty.ty } else { - let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else { + let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index()) + else { fail_out_of_bounds(self, location); return; }; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 9c90b704586..a6052f52917 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -448,7 +448,9 @@ where ty::Closure(_, ref args) => { // Skip lifetime parameters of the enclosing item(s) - args.as_closure().tupled_upvars_ty().visit_with(self); + for upvar in args.as_closure().upvar_tys() { + upvar.visit_with(self); + } args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } @@ -456,7 +458,9 @@ where // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - args.as_generator().tupled_upvars_ty().visit_with(self); + for upvar in args.as_generator().upvar_tys() { + upvar.visit_with(self); + } args.as_generator().return_ty().visit_with(self); args.as_generator().yield_ty().visit_with(self); args.as_generator().resume_ty().visit_with(self); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0f7bed0845c..df39103bc19 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -911,7 +911,7 @@ where if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } - TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) + TyMaybeWithLayout::Ty(args.as_generator().prefix_tys()[i]) } }, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f146f8aa8b4..290c4a48ab0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -827,7 +827,7 @@ pub trait PrettyPrinter<'tcx>: if !args.as_generator().is_valid() { p!("unavailable"); } else { - self = self.comma_sep(args.as_generator().upvar_tys())?; + self = self.comma_sep(args.as_generator().upvar_tys().iter())?; } p!(")"); @@ -900,7 +900,7 @@ pub trait PrettyPrinter<'tcx>: print(args.as_closure().sig_as_fn_ptr_ty()) ); p!(" upvar_tys=("); - self = self.comma_sep(args.as_closure().upvar_tys())?; + self = self.comma_sep(args.as_closure().upvar_tys().iter())?; p!(")"); } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3e023ccdead..1e5f64df9a5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -296,15 +296,13 @@ impl<'tcx> ClosureArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this closure. @@ -436,15 +434,13 @@ impl<'tcx> GeneratorArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this generator. @@ -576,7 +572,7 @@ impl<'tcx> GeneratorArgs<'tcx> { /// This is the types of the fields of a generator which are not stored in a /// variant. #[inline] - pub fn prefix_tys(self) -> impl Iterator> { + pub fn prefix_tys(self) -> &'tcx List> { self.upvar_tys() } } @@ -592,20 +588,18 @@ impl<'tcx> UpvarArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List> { let tupled_tys = match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), }; match tupled_tys.kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } #[inline] diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 1d7d905c937..9e02b027182 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -860,20 +860,14 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind() { - ty::Closure(_, args) => { - let tys: Vec<_> = args.as_closure().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()), // Note that `elaborate_drops` only drops the upvars of a generator, // and this is ok because `open_drop` here can only be reached // within that own generator's resume function. // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. - ty::Generator(_, args, _) => { - let tys: Vec<_> = args.as_generator().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Generator(_, args, _) => self.open_drop_for_tuple(&args.as_generator().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 669135f80bc..797a1a86846 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -856,7 +856,7 @@ fn sanitize_witness<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, witness: Ty<'tcx>, - upvars: Vec>, + upvars: &'tcx ty::List>, layout: &GeneratorLayout<'tcx>, ) { let did = body.source.def_id(); @@ -1471,7 +1471,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let args = args.as_generator(); ( args.discr_ty(tcx), - args.upvar_tys().collect::>(), + args.upvar_tys(), args.witness(), movability == hir::Movability::Movable, ) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index ef989d8c9d6..9484a50e3a9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -291,9 +291,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( return Err(NoSolution); } - constraints.outlives.extend( - args.as_generator().upvar_tys().map(|t| -> ty::GenericArg<'tcx> { t.into() }), - ); + constraints + .outlives + .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.as_generator().resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c29696bc817..1f3cea351bb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2169,7 +2169,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let all = args .as_generator() .upvar_tys() - .chain(iter::once(args.as_generator().witness())) + .iter() + .chain([args.as_generator().witness()]) .collect::>(); Where(obligation.predicate.rebind(all)) } @@ -2210,7 +2211,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Not yet resolved. Ambiguous } else { - Where(obligation.predicate.rebind(args.as_closure().upvar_tys().collect())) + Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec())) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 3500c2cc370..6b4273c03e4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -317,7 +317,9 @@ fn layout_of_uncached<'tcx>( ty::Closure(_, ref args) => { let tys = args.as_closure().upvar_tys(); univariant( - &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::>()?, + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -729,7 +731,7 @@ fn generator_layout<'tcx>( // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let tag_index = args.as_generator().prefix_tys().count(); + let tag_index = args.as_generator().prefix_tys().len(); // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; @@ -748,6 +750,7 @@ fn generator_layout<'tcx>( let prefix_layouts = args .as_generator() .prefix_tys() + .iter() .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) @@ -1062,6 +1065,7 @@ fn variant_info_for_generator<'tcx>( let upvar_fields: Vec<_> = args .as_generator() .upvar_tys() + .iter() .zip(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index f89558a4599..34fd31e49e1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -120,12 +120,16 @@ where _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, args) => { - queue_type(self, args.as_closure().tupled_upvars_ty()); + for upvar in args.as_closure().upvar_tys() { + queue_type(self, upvar); + } } ty::Generator(def_id, args, _) => { let args = args.as_generator(); - queue_type(self, args.tupled_upvars_ty()); + for upvar in args.upvar_tys() { + queue_type(self, upvar); + } let witness = args.witness(); let interior_tys = match witness.kind() { From d6ed6e3904068bed1851d4110fc1f402e78aaadc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 22 Jul 2023 18:23:39 +1000 Subject: [PATCH 15/19] coverage: Consolidate FFI types into one module Coverage FFI types were historically split across two modules, because some of them were needed by code in `rustc_codegen_ssa`. Now that all of the coverage codegen code has been moved into `rustc_codegen_llvm` (#113355), it's possible to move all of the FFI types into a single module, making it easier to see all of them at once. --- .../src/coverageinfo/ffi.rs | 194 +++++++++++++++++ .../src/coverageinfo/map_data.rs | 2 +- .../src/coverageinfo/mapgen.rs | 3 +- .../src/coverageinfo/mod.rs | 6 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 204 +----------------- 5 files changed, 201 insertions(+), 208 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 6ca61aa43d7..7a82d05ce9e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -85,3 +85,197 @@ impl CounterExpression { Self { kind, lhs, rhs } } } + +/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. +/// +/// Must match the layout of `LLVMRustCounterMappingRegionKind`. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub enum RegionKind { + /// A CodeRegion associates some code with a counter + CodeRegion = 0, + + /// An ExpansionRegion represents a file expansion region that associates + /// a source range with the expansion of a virtual source file, such as + /// for a macro instantiation or #include file. + ExpansionRegion = 1, + + /// A SkippedRegion represents a source range with code that was skipped + /// by a preprocessor or similar means. + SkippedRegion = 2, + + /// A GapRegion is like a CodeRegion, but its count is only set as the + /// line execution count when its the only region in the line. + GapRegion = 3, + + /// A BranchRegion represents leaf-level boolean expressions and is + /// associated with two counters, each representing the number of times the + /// expression evaluates to true or false. + BranchRegion = 4, +} + +/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the +/// coverage map, in accordance with the +/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). +/// The struct composes fields representing the `Counter` type and value(s) (injected counter +/// ID, or expression type and operands), the source file (an indirect index into a "filenames +/// array", encoded separately), and source location (start and end positions of the represented +/// code region). +/// +/// Corresponds to struct `llvm::coverage::CounterMappingRegion`. +/// +/// Must match the layout of `LLVMRustCounterMappingRegion`. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct CounterMappingRegion { + /// The counter type and type-dependent counter data, if any. + counter: Counter, + + /// If the `RegionKind` is a `BranchRegion`, this represents the counter + /// for the false branch of the region. + false_counter: Counter, + + /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the + /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes + /// that, in turn, are used to look up the filename for this region. + file_id: u32, + + /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find + /// the mapping regions created as a result of macro expansion, by checking if their file id + /// matches the expanded file id. + expanded_file_id: u32, + + /// 1-based starting line of the mapping region. + start_line: u32, + + /// 1-based starting column of the mapping region. + start_col: u32, + + /// 1-based ending line of the mapping region. + end_line: u32, + + /// 1-based ending column of the mapping region. If the high bit is set, the current + /// mapping region is a gap area. + end_col: u32, + + kind: RegionKind, +} + +impl CounterMappingRegion { + pub(crate) fn code_region( + counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::CodeRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn branch_region( + counter: Counter, + false_counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter, + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::BranchRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn expansion_region( + file_id: u32, + expanded_file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter: Counter::zero(), + false_counter: Counter::zero(), + file_id, + expanded_file_id, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::ExpansionRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn skipped_region( + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter: Counter::zero(), + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::SkippedRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn gap_region( + counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col: (1_u32 << 31) | end_col, + kind: RegionKind::GapRegion, + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 7e981af0a53..f1e68af25d4 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,4 +1,4 @@ -pub use super::ffi::*; +use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 9149b06886b..db9ba0abbde 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,9 +1,8 @@ use crate::common::CodegenCx; use crate::coverageinfo; -use crate::coverageinfo::map_data::{Counter, CounterExpression}; +use crate::coverageinfo::ffi::{Counter, CounterExpression, CounterMappingRegion}; use crate::llvm; -use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::traits::ConstMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c1017ab8d7c..afceb7531e6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -3,10 +3,10 @@ use crate::llvm; use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; -use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage}; +use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion}; +use crate::coverageinfo::map_data::FunctionCoverage; use libc::c_uint; -use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::traits::{ BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, StaticMethods, @@ -27,7 +27,7 @@ use rustc_middle::ty::Ty; use std::cell::RefCell; use std::ffi::CString; -mod ffi; +pub(crate) mod ffi; pub(crate) mod map_data; pub mod mapgen; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7407cfa8c5b..b167facfb02 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,8 +1,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -use crate::coverageinfo::map_data as coverage_map; - use super::debuginfo::{ DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace, @@ -688,204 +686,6 @@ extern "C" { pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); -pub mod coverageinfo { - use super::coverage_map; - - /// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. - /// - /// Must match the layout of `LLVMRustCounterMappingRegionKind`. - #[derive(Copy, Clone, Debug)] - #[repr(C)] - pub enum RegionKind { - /// A CodeRegion associates some code with a counter - CodeRegion = 0, - - /// An ExpansionRegion represents a file expansion region that associates - /// a source range with the expansion of a virtual source file, such as - /// for a macro instantiation or #include file. - ExpansionRegion = 1, - - /// A SkippedRegion represents a source range with code that was skipped - /// by a preprocessor or similar means. - SkippedRegion = 2, - - /// A GapRegion is like a CodeRegion, but its count is only set as the - /// line execution count when its the only region in the line. - GapRegion = 3, - - /// A BranchRegion represents leaf-level boolean expressions and is - /// associated with two counters, each representing the number of times the - /// expression evaluates to true or false. - BranchRegion = 4, - } - - /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the - /// coverage map, in accordance with the - /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). - /// The struct composes fields representing the `Counter` type and value(s) (injected counter - /// ID, or expression type and operands), the source file (an indirect index into a "filenames - /// array", encoded separately), and source location (start and end positions of the represented - /// code region). - /// - /// Corresponds to struct `llvm::coverage::CounterMappingRegion`. - /// - /// Must match the layout of `LLVMRustCounterMappingRegion`. - #[derive(Copy, Clone, Debug)] - #[repr(C)] - pub struct CounterMappingRegion { - /// The counter type and type-dependent counter data, if any. - counter: coverage_map::Counter, - - /// If the `RegionKind` is a `BranchRegion`, this represents the counter - /// for the false branch of the region. - false_counter: coverage_map::Counter, - - /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the - /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes - /// that, in turn, are used to look up the filename for this region. - file_id: u32, - - /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find - /// the mapping regions created as a result of macro expansion, by checking if their file id - /// matches the expanded file id. - expanded_file_id: u32, - - /// 1-based starting line of the mapping region. - start_line: u32, - - /// 1-based starting column of the mapping region. - start_col: u32, - - /// 1-based ending line of the mapping region. - end_line: u32, - - /// 1-based ending column of the mapping region. If the high bit is set, the current - /// mapping region is a gap area. - end_col: u32, - - kind: RegionKind, - } - - impl CounterMappingRegion { - pub(crate) fn code_region( - counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::CodeRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn branch_region( - counter: coverage_map::Counter, - false_counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter, - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::BranchRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn expansion_region( - file_id: u32, - expanded_file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: coverage_map::Counter::zero(), - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::ExpansionRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn skipped_region( - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: coverage_map::Counter::zero(), - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::SkippedRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn gap_region( - counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col: (1_u32 << 31) | end_col, - kind: RegionKind::GapRegion, - } - } - } -} - pub mod debuginfo { use super::{InvariantOpaque, Metadata}; use bitflags::bitflags; @@ -1911,9 +1711,9 @@ extern "C" { pub fn LLVMRustCoverageWriteMappingToBuffer( VirtualFileMappingIDs: *const c_uint, NumVirtualFileMappingIDs: c_uint, - Expressions: *const coverage_map::CounterExpression, + Expressions: *const crate::coverageinfo::ffi::CounterExpression, NumExpressions: c_uint, - MappingRegions: *const coverageinfo::CounterMappingRegion, + MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion, NumMappingRegions: c_uint, BufferOut: &RustString, ); From c94dc72a1cc578da622941095104a4426161b503 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 30 Jun 2023 20:41:59 -0400 Subject: [PATCH 16/19] Clarify documentation for `CStr` * Better differentiate summaries for `from_bytes_until_nul` and `from_bytes_with_nul` * Add some links where they may be helpful --- library/core/src/ffi/c_str.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 3de9188baf6..db12bdcebe7 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -197,8 +197,8 @@ impl CStr { /// /// This function will wrap the provided `ptr` with a `CStr` wrapper, which /// allows inspection and interoperation of non-owned C strings. The total - /// size of the raw C string must be smaller than `isize::MAX` **bytes** - /// in memory due to calling the `slice::from_raw_parts` function. + /// size of the terminated buffer must be smaller than [`isize::MAX`] **bytes** + /// in memory (a restriction from [`slice::from_raw_parts`]). /// /// # Safety /// @@ -295,11 +295,11 @@ impl CStr { } } - /// Creates a C string wrapper from a byte slice. + /// Creates a C string wrapper from a byte slice with any number of nuls. /// /// This method will create a `CStr` from any byte slice that contains at - /// least one nul byte. The caller does not need to know or specify where - /// the nul byte is located. + /// least one nul byte. Unlike with [`CStr::from_bytes_with_nul`], the caller + /// does not need to know where the nul byte is located. /// /// If the first byte is a nul character, this method will return an /// empty `CStr`. If multiple nul characters are present, the `CStr` will @@ -341,7 +341,8 @@ impl CStr { } } - /// Creates a C string wrapper from a byte slice. + /// Creates a C string wrapper from a byte slice with exactly one nul + /// terminator. /// /// This function will cast the provided `bytes` to a `CStr` /// wrapper after ensuring that the byte slice is nul-terminated From 90db1132c76f0c7dae0bee33cbadbb1390a5881f Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 2 Aug 2023 16:21:45 +0800 Subject: [PATCH 17/19] get auto traits for parallel rustc Signed-off-by: SparrowLii --- compiler/rustc_ast/src/format.rs | 6 ------ src/librustdoc/clean/utils.rs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index 699946f307b..805596ff00a 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -67,12 +67,6 @@ pub struct FormatArguments { names: FxHashMap, } -// FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930. -#[cfg(parallel_compiler)] -unsafe impl Sync for FormatArguments {} -#[cfg(parallel_compiler)] -unsafe impl Send for FormatArguments {} - impl FormatArguments { pub fn new() -> Self { Self { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 5c8db3b8774..43d8bcae8e2 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -480,12 +480,6 @@ pub(crate) fn get_auto_trait_and_blanket_impls( cx: &mut DocContext<'_>, item_def_id: DefId, ) -> impl Iterator { - // FIXME: To be removed once `parallel_compiler` bugs are fixed! - // More information in . - if cfg!(parallel_compiler) { - return vec![].into_iter().chain(vec![].into_iter()); - } - let auto_impls = cx .sess() .prof From 4fec845c3f971c0ec77fccf460fe981fc50a7a12 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 29 Jul 2023 08:20:25 +0000 Subject: [PATCH 18/19] Remove constness from `TraitPredicate` --- .../src/type_check/canonical.rs | 6 +- .../src/transform/check_consts/check.rs | 2 +- .../src/transform/check_consts/qualifs.rs | 4 +- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- .../src/astconv/object_safety.rs | 15 ++--- compiler/rustc_hir_analysis/src/bounds.rs | 3 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 13 +--- .../src/collect/predicates_of.rs | 16 ++--- .../src/impl_wf_check/min_specialization.rs | 42 ++---------- .../rustc_hir_analysis/src/variance/mod.rs | 1 - compiler/rustc_hir_typeck/src/expr.rs | 1 - .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 5 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 --- compiler/rustc_hir_typeck/src/method/mod.rs | 10 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_infer/src/traits/engine.rs | 2 +- compiler/rustc_infer/src/traits/mod.rs | 7 -- compiler/rustc_infer/src/traits/util.rs | 6 +- compiler/rustc_middle/src/ty/mod.rs | 65 +------------------ compiler/rustc_middle/src/ty/print/pretty.rs | 9 +-- compiler/rustc_middle/src/ty/relate.rs | 1 - .../rustc_middle/src/ty/structural_impls.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 16 +---- compiler/rustc_privacy/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- .../src/solve/assembly/mod.rs | 1 - .../src/traits/auto_trait.rs | 2 - .../src/traits/engine.rs | 2 +- .../src/traits/error_reporting/mod.rs | 30 ++++----- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/object_safety.rs | 1 - .../src/traits/project.rs | 8 +-- .../src/traits/select/candidate_assembly.rs | 7 +- .../src/traits/select/confirmation.rs | 15 ++--- .../src/traits/select/mod.rs | 11 +--- .../src/traits/specialize/mod.rs | 6 +- .../rustc_trait_selection/src/traits/util.rs | 12 ++-- .../src/traits/vtable.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 40 ++---------- src/librustdoc/clean/mod.rs | 5 +- src/tools/clippy/clippy_lints/src/derive.rs | 4 +- .../clippy/clippy_lints/src/eta_reduction.rs | 3 +- .../clippy_utils/src/qualify_min_const_fn.rs | 5 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- tests/ui/consts/const-float-classify.rs | 3 +- tests/ui/consts/const-float-classify.stderr | 11 ++++ ...constifconst-call-in-const-position.stderr | 18 +++-- .../ui/consts/unstable-const-fn-in-libcore.rs | 1 + .../unstable-const-fn-in-libcore.stderr | 17 ++++- .../generic-const-items/const-trait-impl.rs | 3 +- .../const-trait-impl.stderr | 11 ++++ .../impl-trait/normalize-tait-in-const.stderr | 17 ++++- .../assoc-type-const-bound-usage.rs | 3 +- .../assoc-type-const-bound-usage.stderr | 11 ++++ .../const-closure-trait-method-fail.stderr | 20 ++---- .../const-closure-trait-method.rs | 3 +- .../const-closure-trait-method.stderr | 15 +++++ .../const-closures.rs | 3 +- .../const-closures.stderr | 39 +++++++++++ .../const-drop-fail-2.stderr | 21 +++++- .../const-drop.precise.stderr | 13 +++- .../const-drop.stock.stderr | 13 +++- ...ault-method-body-is-const-body-checking.rs | 2 +- ...-method-body-is-const-same-trait-ck.stderr | 4 +- ...fault-bound-non-const-specialized-bound.rs | 3 +- ...t-bound-non-const-specialized-bound.stderr | 14 ---- .../const-default-const-specialized.rs | 3 +- .../const-default-const-specialized.stderr | 11 ++++ .../non-const-default-const-specialized.rs | 4 +- ...non-const-default-const-specialized.stderr | 11 ++++ .../specializing-constness.rs | 2 +- .../specializing-constness.stderr | 8 +-- .../super-traits-fail-3.nn.stderr | 6 +- .../super-traits-fail-3.ny.stderr | 4 +- .../super-traits-fail-3.rs | 3 +- .../super-traits-fail-3.yn.stderr | 2 +- .../super-traits-fail-3.yy.stderr | 11 ++++ .../rfc-2632-const-trait-impl/super-traits.rs | 3 +- .../super-traits.stderr | 11 ++++ .../tilde-const-and-const-params.rs | 1 + .../tilde-const-and-const-params.stderr | 11 +++- .../tilde_const_on_impl_bound.rs | 3 +- .../tilde_const_on_impl_bound.stderr | 11 ++++ .../trait-where-clause-const.rs | 2 +- .../trait-where-clause-const.stderr | 51 +++++++++++++++ .../trait-where-clause-run.rs | 3 +- .../trait-where-clause-run.stderr | 11 ++++ .../trait-where-clause-self-referential.rs | 3 +- ...trait-where-clause-self-referential.stderr | 11 ++++ 90 files changed, 446 insertions(+), 390 deletions(-) create mode 100644 tests/ui/consts/const-float-classify.stderr create mode 100644 tests/ui/generic-const-items/const-trait-impl.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index c19fbf20ca5..16f5e68a06f 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -90,11 +90,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait( - ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }, + ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }, ))), locations, category, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index ad5ffa6511f..b077c10907e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -746,6 +746,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } // Attempting to call a trait method? + // FIXME(effects) do we need this? if let Some(trait_id) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); if !self.tcx.features().const_trait_impl { @@ -761,7 +762,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args); - let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index b152644a551..8293bdfd969 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -155,12 +155,12 @@ impl Qualif for NeedsNonConstDrop { return false; } + // FIXME(effects) constness let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), cx.param_env, - ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]) - .with_constness(ty::BoundConstness::ConstIfConst), + ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]), ); let infcx = cx.tcx.infer_ctxt().build(); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index bc109e7ad51..b40e3123522 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -713,7 +713,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); debug!(?poly_trait_ref, ?assoc_bindings); - bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity); + bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index a36ec0c5730..30c2ab8f545 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -62,11 +62,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match bound_pred.skip_binder() { ty::ClauseKind::Trait(trait_pred) => { assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push(( - bound_pred.rebind(trait_pred.trait_ref), - span, - trait_pred.constness, - )); + trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span)); } ty::ClauseKind::Projection(proj) => { projection_bounds.push((bound_pred.rebind(proj), span)); @@ -86,7 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); + traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) @@ -126,7 +122,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if regular_traits.is_empty() && auto_traits.is_empty() { let trait_alias_span = trait_bounds .iter() - .map(|&(trait_ref, _, _)| trait_ref.def_id()) + .map(|&(trait_ref, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) .map(|trait_ref| tcx.def_span(trait_ref)); let reported = @@ -157,10 +153,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let regular_traits_refs_spans = trait_bounds .into_iter() - .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); + .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); - for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, ty::BoundConstness::NotConst); + for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); for pred in traits::elaborate(tcx, [base_pred]) { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 531100e1fe6..1d9ae2b9cb7 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -42,13 +42,12 @@ impl<'tcx> Bounds<'tcx> { tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, span: Span, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) { self.clauses.push(( trait_ref .map_bound(|trait_ref| { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity }) + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) }) .to_predicate(tcx), span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 6206ba508ae..e64848da86b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -194,7 +194,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. match (tcx.impl_polarity(def_id), impl_.polarity) { (ty::ImplPolarity::Positive, _) => { - check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness); + check_impl(tcx, item, impl_.self_ty, &impl_.of_trait); } (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => { // FIXME(#27579): what amount of WF checking do we need for neg impls? @@ -1191,7 +1191,6 @@ fn check_impl<'tcx>( item: &'tcx hir::Item<'tcx>, ast_self_ty: &hir::Ty<'_>, ast_trait_ref: &Option>, - constness: hir::Constness, ) { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { match ast_trait_ref { @@ -1205,14 +1204,8 @@ fn check_impl<'tcx>( Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); - let trait_pred = ty::TraitPredicate { - trait_ref, - constness: match constness { - hir::Constness::Const => ty::BoundConstness::ConstIfConst, - hir::Constness::NotConst => ty::BoundConstness::NotConst, - }, - polarity: ty::ImplPolarity::Positive, - }; + let trait_pred = + ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }; let mut obligations = traits::wf::trait_obligations( wfcx.infcx, wfcx.param_env, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ab3b2dde078..2950ce683a3 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate}; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with @@ -37,17 +37,10 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // from the trait itself that *shouldn't* be shown as the source of // an obligation and instead be skipped. Otherwise we'd use // `tcx.def_span(def_id);` - - let constness = if tcx.has_attr(def_id, sym::const_trait) { - ty::BoundConstness::ConstIfConst - } else { - ty::BoundConstness::NotConst - }; - let span = rustc_span::DUMMY_SP; result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx), + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), span, )))); } @@ -204,7 +197,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); + predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); } // Collect the region predicates that were declared inline as @@ -777,8 +770,7 @@ pub(super) fn type_param_predicates( if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id()); - extend = - Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); + extend = Some((identity_trait_ref.to_predicate(tcx), item.span)); } generics } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 8b2c93d8fd3..3760195a5e8 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -431,45 +431,13 @@ fn check_predicates<'tcx>( /// /// So we make that check in this function and try to raise a helpful error message. fn trait_predicates_eq<'tcx>( - tcx: TyCtxt<'tcx>, + _tcx: TyCtxt<'tcx>, predicate1: ty::Predicate<'tcx>, predicate2: ty::Predicate<'tcx>, - span: Span, + _span: Span, ) -> bool { - let pred1_kind = predicate1.kind().skip_binder(); - let pred2_kind = predicate2.kind().skip_binder(); - let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)), - ) => (pred1, pred2), - // Just use plain syntactic equivalence if either of the predicates aren't - // trait predicates or have bound vars. - _ => return predicate1 == predicate2, - }; - - let predicates_equal_modulo_constness = { - let pred1_unconsted = - ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred1 }; - let pred2_unconsted = - ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred2 }; - pred1_unconsted == pred2_unconsted - }; - - if !predicates_equal_modulo_constness { - return false; - } - - // Check that the predicate on the specializing impl is at least as const as - // the one on the base. - match (trait_pred2.constness, trait_pred1.constness) { - (ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => { - tcx.sess.emit_err(errors::MissingTildeConst { span }); - } - _ => {} - } - - true + // FIXME(effects) + predicate1 == predicate2 } #[instrument(level = "debug", skip(tcx))] @@ -482,7 +450,6 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc // items. ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, - constness: _, polarity: _, })) => { if !matches!( @@ -536,7 +503,6 @@ fn trait_predicate_kind<'tcx>( match predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, - constness: _, polarity: _, })) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 1ef257e87d6..6952a3fa66f 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -156,7 +156,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc match pred.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: _, args, .. }, - constness: _, polarity: _, }) => { for subst in &args[1..] { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8f5737dd4ad..eb6359ed72f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2988,7 +2988,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Binder::dummy(ty::TraitPredicate { trait_ref: impl_trait_ref, polarity: ty::ImplPolarity::Positive, - constness: ty::BoundConstness::NotConst, }), |derived| { traits::ImplDerivedObligation(Box::new( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index ecafb50f420..1433c67d55d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1461,10 +1461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env, bounds, ) { - // N.B. We are remapping all predicates to non-const since we don't know if we just - // want them as function pointers or we are calling them from a const-context. The - // actual checking will occur in `rustc_const_eval::transform::check_consts`. - self.register_predicate(obligation.without_const(self.tcx)); + self.register_predicate(obligation); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e102c51c7ee..e3d97b41980 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1856,19 +1856,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.adjust_fulfillment_error_for_expr_obligation(error) || before_span != error.obligation.cause.span { - // Store both the predicate and the predicate *without constness* - // since sometimes we instantiate and check both of these in a - // method call, for example. remap_cause.insert(( before_span, error.obligation.predicate, error.obligation.cause.clone(), )); - remap_cause.insert(( - before_span, - error.obligation.predicate.without_const(self.tcx), - error.obligation.cause.clone(), - )); } else { // If it failed to be adjusted once around, it may be adjusted // via the "remap cause" mapping the second time... diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 356e7022aea..597696843c4 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -341,15 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct an obligation let poly_trait_ref = ty::Binder::dummy(trait_ref); - ( - traits::Obligation::new( - self.tcx, - cause, - self.param_env, - poly_trait_ref.without_const(), - ), - args, - ) + (traits::Obligation::new(self.tcx, cause, self.param_env, poly_trait_ref), args) } /// `lookup_method_in_trait` is used for overloaded operators. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 05eed1923d1..7164102a30e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1599,8 +1599,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - let predicate = - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); + let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx); parent_pred = Some(predicate); let obligation = traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f6c07931023..b9d8c5a7540 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.without_const(), + poly_trait_ref, ); self.predicate_may_hold(&obligation) }) diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 11f43469400..64b9714c7c0 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -25,7 +25,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(infcx.tcx), }, ); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index a9da6104b38..dc41630196b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -77,13 +77,6 @@ impl<'tcx> PredicateObligation<'tcx> { recursion_depth: self.recursion_depth, }) } - - pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { - self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const())))); - } - self - } } impl<'tcx> PolyTraitObligation<'tcx> { diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 87ba6b3ec50..93dfbe63bcd 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -264,11 +264,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { }; let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| { - // when parent predicate is non-const, elaborate it to non-const predicates. - if data.constness == ty::BoundConstness::NotConst { - clause = clause.without_const(tcx); - } + predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { elaboratable.child_with_derived_cause( clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), span, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b4c834f766..6b0f0132062 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -498,11 +498,9 @@ impl<'tcx> Predicate<'tcx> { .map_bound(|kind| match kind { PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, - constness, polarity, })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, - constness, polarity: polarity.flip()?, }))), @@ -513,19 +511,6 @@ impl<'tcx> Predicate<'tcx> { Some(tcx.mk_predicate(kind)) } - pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { - if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() - && constness != BoundConstness::NotConst - { - self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - constness: BoundConstness::NotConst, - polarity, - })))); - } - self - } - #[instrument(level = "debug", skip(tcx), ret)] pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind().skip_binder() { @@ -629,10 +614,6 @@ impl<'tcx> Clause<'tcx> { None } } - - pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - self.as_predicate().without_const(tcx).expect_clause() - } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -852,8 +833,6 @@ impl<'tcx> Clause<'tcx> { pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, - pub constness: BoundConstness, - /// If polarity is Positive: we are proving that the trait is implemented. /// /// If polarity is Negative: we are proving that a negative impl of this trait @@ -878,24 +857,6 @@ impl<'tcx> TraitPredicate<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { self.trait_ref.self_ty() } - - #[inline] - pub fn is_const_if_const(self) -> bool { - self.constness == BoundConstness::ConstIfConst - } - - pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { - match (self.constness, constness) { - (BoundConstness::NotConst, _) - | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, - (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, - } - } - - pub fn without_const(mut self) -> Self { - self.constness = BoundConstness::NotConst; - self - } } impl<'tcx> PolyTraitPredicate<'tcx> { @@ -908,11 +869,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| trait_ref.self_ty()) } - #[inline] - pub fn is_const_if_const(self) -> bool { - self.skip_binder().is_const_if_const() - } - #[inline] pub fn polarity(self) -> ImplPolarity { self.skip_binder().polarity @@ -1287,7 +1243,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { #[inline(always)] fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { - self.without_const() + TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } } } @@ -1328,7 +1284,6 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }) } @@ -1826,24 +1781,6 @@ impl<'tcx> ParamEnv<'tcx> { } } -// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that -// the constness of trait bounds is being propagated correctly. -impl<'tcx> PolyTraitRef<'tcx> { - #[inline] - pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness, - polarity: ty::ImplPolarity::Positive, - }) - } - - #[inline] - pub fn without_const(self) -> PolyTraitPredicate<'tcx> { - self.with_constness(BoundConstness::NotConst) - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] #[derive(HashStable, Lift)] pub struct ParamEnvAnd<'tcx, T> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 290c4a48ab0..6e68022031a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2806,10 +2806,7 @@ define_print_and_forward_display! { } TraitPredPrintModifiersAndPath<'tcx> { - if let ty::BoundConstness::ConstIfConst = self.0.constness { - p!("~const ") - } - + // FIXME(effects) print `~const` here if let ty::ImplPolarity::Negative = self.0.polarity { p!("!") } @@ -2843,9 +2840,7 @@ define_print_and_forward_display! { ty::TraitPredicate<'tcx> { p!(print(self.trait_ref.self_ty()), ": "); - if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl { - p!("~const "); - } + // FIXME(effects) print `~const` here if let ty::ImplPolarity::Negative = self.polarity { p!("!"); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index bf9adabdab1..47512d350e5 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -826,7 +826,6 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, - constness: relation.relate(a.constness, b.constness)?, polarity: relation.relate(a.polarity, b.polarity)?, }) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6b6f0e8990..1347b35556d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -172,9 +172,7 @@ impl fmt::Debug for ty::ParamConst { impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let ty::BoundConstness::ConstIfConst = self.constness { - write!(f, "~const ")?; - } + // FIXME(effects) printing? write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1e5f64df9a5..a695febf087 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -722,7 +722,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) + self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) } ExistentialPredicate::Projection(p) => { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) @@ -737,7 +737,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); ty::TraitRef::new(tcx, did, err_args) }; - self.rebind(trait_ref).without_const().to_predicate(tcx) + self.rebind(trait_ref).to_predicate(tcx) } } } @@ -869,18 +869,6 @@ impl<'tcx> TraitRef<'tcx> { ) } - /// Converts this trait ref to a trait predicate with a given `constness` and a positive polarity. - #[inline] - pub fn with_constness(self, constness: ty::BoundConstness) -> ty::TraitPredicate<'tcx> { - ty::TraitPredicate { trait_ref: self, constness, polarity: ty::ImplPolarity::Positive } - } - - /// Converts this trait ref to a trait predicate without `const` and a positive polarity. - #[inline] - pub fn without_const(self) -> ty::TraitPredicate<'tcx> { - self.with_constness(ty::BoundConstness::NotConst) - } - #[inline] pub fn self_ty(&self) -> Ty<'tcx> { self.args.type_at(0) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5fa780a372b..af9efb82beb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -147,7 +147,7 @@ where fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow { match clause.kind().skip_binder() { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 6efc1e7302c..38153cccfdd 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -72,7 +72,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(self.tcx), }; self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 5ec48c7ac57..8bf003f863e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -727,7 +727,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.tcx(), ty::TraitPredicate { trait_ref: self_trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }, ); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 94d3cd035aa..ba5000da6cd 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -97,7 +97,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { orig_env, ty::TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: if polarity { ImplPolarity::Positive } else { @@ -260,7 +259,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]), - constness: ty::BoundConstness::NotConst, // Auto traits are positive polarity: ty::ImplPolarity::Positive, })); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 61f693e1bd1..820973dc090 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), }); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 95485850d0e..eae13eb6302 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -100,7 +100,6 @@ pub trait InferCtxtExt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; } @@ -356,7 +355,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { self.commit_if_ok(|_| { @@ -372,12 +370,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, }); + // FIXME(effects) let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); let obligation = Obligation::new( self.tcx, ObligationCause::dummy(), param_env, - ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }), + ty.rebind(ty::TraitPredicate { trait_ref, polarity }), ); let ocx = ObligationCtxt::new(self); ocx.register_obligation(obligation); @@ -689,8 +688,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - let predicate_is_const = ty::BoundConstness::ConstIfConst - == trait_predicate.skip_binder().constness; + // FIXME(effects) + let predicate_is_const = false; if self.tcx.sess.has_errors().is_some() && trait_predicate.references_error() @@ -1909,9 +1908,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .all_impls(trait_pred.def_id()) .filter_map(|def_id| { if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative - || !trait_pred - .skip_binder() - .is_constness_satisfied_by(self.tcx.constness(def_id)) || !self.tcx.is_user_visible_dep(def_id.krate) { return None; @@ -2996,7 +2992,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( obligation.param_env, trait_ref.self_ty(), - trait_predicate.skip_binder().constness, trait_predicate.skip_binder().polarity, ) { @@ -3099,14 +3094,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn maybe_add_note_for_unsatisfied_const( &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, + _obligation: &PredicateObligation<'tcx>, + _trait_ref: ty::PolyTraitRef<'tcx>, + _trait_predicate: &ty::PolyTraitPredicate<'tcx>, + _err: &mut Diagnostic, + _span: Span, ) -> UnsatisfiedConst { - let mut unsatisfied_const = UnsatisfiedConst(false); - if trait_predicate.is_const_if_const() { + let unsatisfied_const = UnsatisfiedConst(false); + // FIXME(effects) + /* if trait_predicate.is_const_if_const() { let non_const_predicate = trait_ref.without_const(); let non_const_obligation = Obligation { cause: obligation.cause.clone(), @@ -3126,7 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ), ); } - } + } */ unsatisfied_const } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 593f669e9bb..d2210c6d5d9 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -133,7 +133,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, ) -> bool { let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]); - pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const()) + pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref) } /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 76752edc4ae..5823b4508d9 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -574,7 +574,6 @@ fn virtual_call_violation_for_method<'tcx>( // implement auto traits if the underlying type does as well. if let ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: pred_trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }) = pred.kind().skip_binder() && pred_trait_ref.self_ty() == tcx.types.self_param diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 98f45826727..3d800421b76 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1306,7 +1306,7 @@ fn normalize_to_error<'a, 'tcx>( cause, recursion_depth: depth, param_env, - predicate: trait_ref.without_const().to_predicate(selcx.tcx()), + predicate: trait_ref.to_predicate(selcx.tcx()), }; let tcx = selcx.infcx.tcx; let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin { @@ -1867,8 +1867,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), - ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]) - .without_const(), + ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), ), ) => { @@ -2152,8 +2151,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( LangItem::Sized, obligation.cause.span(), [self_ty], - ) - .without_const(); + ); obligations.push(obligation.with(tcx, sized_predicate)); } (metadata_ty.into(), obligations) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b9f31be25b1..8f2f02a5e41 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -154,9 +154,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - candidates - .vec - .extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness))); + // FIXME(effects) proper constness needed? + candidates.vec.extend( + result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)), + ); } /// Given an obligation like ``, searches the obligations that the caller diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7140fedb74a..bf09681c66d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -59,7 +59,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ParamCandidate(param) => { let obligations = self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); - ImplSource::Param(param.skip_binder().constness, obligations) + // FIXME(effects) + ImplSource::Param(ty::BoundConstness::NotConst, obligations) } ImplCandidate(impl_def_id) => { @@ -128,14 +129,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { subobligation.set_depth_from_parent(obligation.recursion_depth); } - if !obligation.predicate.is_const_if_const() { - // normalize nested predicates according to parent predicate's constness. - impl_src = impl_src.map(|mut o| { - o.predicate = o.predicate.without_const(self.tcx()); - o - }); - } - Ok(impl_src) } @@ -1305,6 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If we have a projection type, make sure to normalize it so we replace it // with a fresh infer variable ty::Alias(ty::Projection | ty::Inherent, ..) => { + // FIXME(effects) this needs constness let predicate = normalize_with_depth_to( self, obligation.param_env, @@ -1317,7 +1311,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.span, [nested_ty], ), - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }), &mut nested, @@ -1336,6 +1329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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) _ => { + // FIXME(effects) this needs constness let predicate = self_ty.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef::from_lang_item( self.tcx(), @@ -1343,7 +1337,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.span, [nested_ty], ), - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 367a196dcb8..5da8d838db2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1583,7 +1583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> { + ) -> smallvec::SmallVec<[usize; 2]> { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); @@ -1632,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => false, } }) { - return Some((idx, pred.constness)); + return Some(idx); } } None @@ -1820,7 +1820,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { (ParamCandidate(other), ParamCandidate(victim)) => { let same_except_bound_vars = other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && other.skip_binder().constness == victim.skip_binder().constness && other.skip_binder().polarity == victim.skip_binder().polarity && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { @@ -1830,12 +1829,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. DropVictim::drop_if(other.bound_vars().len() <= victim.bound_vars().len()) - } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && victim.skip_binder().constness == ty::BoundConstness::NotConst - && other.skip_binder().polarity == victim.skip_binder().polarity - { - // Drop otherwise equivalent non-const candidates in favor of const candidates. - DropVictim::Yes } else { DropVictim::No } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 61e631c438d..729cf2f3313 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -500,16 +500,12 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti let mut pretty_predicates = Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); - for (mut p, _) in predicates { + for (p, _) in predicates { if let Some(poly_trait_ref) = p.as_trait_clause() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); continue; } - - if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness { - p = p.without_const(tcx); - } } pretty_predicates.push(p.to_string()); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 4c27fe8b29b..a76272e9d09 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -101,7 +101,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.tcx; let trait_ref = item.trait_ref(); - let pred = trait_ref.without_const().to_predicate(tcx); + let pred = trait_ref.to_predicate(tcx); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); @@ -113,9 +113,13 @@ impl<'tcx> TraitAliasExpander<'tcx> { // Don't recurse if this trait alias is already on the stack for the DFS search. let anon_pred = anonymize_predicate(tcx, pred); - if item.path.iter().rev().skip(1).any(|&(tr, _)| { - anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred - }) { + if item + .path + .iter() + .rev() + .skip(1) + .any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred) + { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 3964dda1fdb..427ac368432 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -86,7 +86,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( let mut emit_vptr_on_new_entry = false; let mut visited = PredicateSet::new(tcx); - let predicate = trait_ref.without_const().to_predicate(tcx); + let predicate = trait_ref.to_predicate(tcx); let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> = smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))]; visited.insert(predicate); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 5f6bb04fda4..f26310665f9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -348,11 +348,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } // if the trait predicate is not const, the wf obligations should not be const as well. - let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { - self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.args) - } else { - self.nominal_obligations(trait_ref.def_id, trait_ref.args) - }; + let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.args); debug!("compute_trait_pred obligations {:?}", obligations); let param_env = self.param_env; @@ -445,8 +441,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // `i32: Clone` // `i32: Copy` // ] - // Projection types do not require const predicates. - let obligations = self.nominal_obligations_without_const(data.def_id, data.args); + let obligations = self.nominal_obligations(data.def_id, data.args); self.out.extend(obligations); self.compute_projection_args(data.args); @@ -472,8 +467,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.recursion_depth, &mut self.out, ); - // Inherent projection types do not require const predicates. - let obligations = self.nominal_obligations_without_const(data.def_id, args); + let obligations = self.nominal_obligations(data.def_id, args); self.out.extend(obligations); } @@ -516,7 +510,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(trait_ref).without_const(), + ty::Binder::dummy(trait_ref), )); } } @@ -667,7 +661,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } ty::FnDef(did, args) => { - let obligations = self.nominal_obligations_without_const(did, args); + let obligations = self.nominal_obligations(did, args); self.out.extend(obligations); } @@ -822,11 +816,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn nominal_obligations_inner( + fn nominal_obligations( &mut self, def_id: DefId, args: GenericArgsRef<'tcx>, - remap_constness: bool, ) -> Vec> { let predicates = self.tcx().predicates_of(def_id); let mut origins = vec![def_id; predicates.predicates.len()]; @@ -841,16 +834,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { debug_assert_eq!(predicates.predicates.len(), origins.len()); iter::zip(predicates, origins.into_iter().rev()) - .map(|((mut pred, span), origin_def_id)| { + .map(|((pred, span), origin_def_id)| { let code = if span.is_dummy() { traits::ItemObligation(origin_def_id) } else { traits::BindingObligation(origin_def_id, span) }; let cause = self.cause(code); - if remap_constness { - pred = pred.without_const(self.tcx()); - } traits::Obligation::with_depth( self.tcx(), cause, @@ -863,22 +853,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .collect() } - fn nominal_obligations( - &mut self, - def_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> Vec> { - self.nominal_obligations_inner(def_id, args, false) - } - - fn nominal_obligations_without_const( - &mut self, - def_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> Vec> { - self.nominal_obligations_inner(def_id, args, true) - } - fn from_object_ty( &mut self, ty: Ty<'tcx>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6ec8f516366..a5efcc989f6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -370,9 +370,8 @@ fn clean_poly_trait_predicate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Option { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if pred.skip_binder().constness == ty::BoundConstness::ConstIfConst - && Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() - { + // FIXME(effects) check constness + if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() { return None; } diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index e3f2026cfe9..9900dbdee6b 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, + self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -523,7 +523,6 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> if let ClauseKind::Trait(p) = p.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() - && p.constness == BoundConstness::NotConst { // Flag types which already have an `Eq` bound. params[self_ty.index as usize].1 = false; @@ -535,7 +534,6 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), - constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, }) .to_predicate(tcx) diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 8d6fb8438b6..ba7957b0dec 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -10,7 +10,7 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPat use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ - self, Binder, BoundConstness, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, + self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, GenericArgsRef, ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -171,7 +171,6 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { = cx.tcx.infer_ctxt().build().type_implements_fn_trait( cx.param_env, Binder::bind_with_vars(callee_ty_adjusted, List::empty()), - BoundConstness::NotConst, ImplPolarity::Positive, ) && path_to_local(callee) .map_or( diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index a98e2038d5f..f0a777c5b89 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::{ImplSource, ObligationCause, BuiltinImplSource}; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, BoundConstness, GenericArgKind, TraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt}; use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; @@ -399,11 +399,12 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return true; } + // FIXME(effects) constness let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), ConstCx::new(tcx, body).param_env, - TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst), + TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]), ); let infcx = tcx.infer_ctxt().build(); diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index d0e15aa8bb3..71766480535 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -267,7 +267,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( cause: ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), }; infcx .evaluate_obligation(&obligation) diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs index 3a5d5bb46e9..877ce02193c 100644 --- a/tests/ui/consts/const-float-classify.rs +++ b/tests/ui/consts/const-float-classify.rs @@ -1,5 +1,6 @@ // compile-flags: -Zmir-opt-level=0 -// run-pass +// known-bug: #110395 +// FIXME run-pass #![feature(const_float_bits_conv)] #![feature(const_float_classify)] diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr new file mode 100644 index 00000000000..a23d81c0ebe --- /dev/null +++ b/tests/ui/consts/const-float-classify.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `>::eq` in constant functions + --> $DIR/const-float-classify.rs:31:7 + | +LL | x.eq(y) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index d4a445120a2..6eee466611c 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -7,12 +7,22 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] = note: see issue #76560 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0080]: evaluation of `foo::<()>::{constant#0}` failed +error[E0015]: cannot call non-const fn `::a` in constants + --> $DIR/constifconst-call-in-const-position.rs:17:9 + | +LL | [0; T::a()] + | ^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::a` in constants --> $DIR/constifconst-call-in-const-position.rs:16:38 | LL | const fn foo() -> [u8; T::a()] { - | ^^^^^^ calling non-const function `<() as Tr>::a` + | ^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.rs b/tests/ui/consts/unstable-const-fn-in-libcore.rs index ca4ed8f0b47..61e28117ed4 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.rs +++ b/tests/ui/consts/unstable-const-fn-in-libcore.rs @@ -20,6 +20,7 @@ impl Opt { match self { Opt::Some(t) => t, Opt::None => f(), + //~^ ERROR cannot call } } } diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index e5b00dd07ab..95d7b7e8537 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,3 +1,15 @@ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/unstable-const-fn-in-libcore.rs:22:26 + | +LL | Opt::None => f(), + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { + | +++++++++++++++++++++++++++++ + error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:17:60 | @@ -16,6 +28,7 @@ LL | const fn unwrap_or_else T>(self, f: F) -> T { LL | } | - value is dropped here -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0493`. +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index 8da1448df4f..d30f7af170d 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass // Test that we can call methods from const trait impls inside of generic const items. diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr new file mode 100644 index 00000000000..34360c581d5 --- /dev/null +++ b/tests/ui/generic-const-items/const-trait-impl.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::create` in constants + --> $DIR/const-trait-impl.rs:11:37 + | +LL | const CREATE: T = T::create(); + | ^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 06247e2ea1e..5fbba9a85ca 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,3 +1,15 @@ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/normalize-tait-in-const.rs:26:5 + | +LL | fun(filter_positive()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { + | ++++++++++++++++++++++++++++++++++++ + error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/normalize-tait-in-const.rs:25:79 | @@ -7,6 +19,7 @@ LL | fun(filter_positive()); LL | } | - value is dropped here -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0493`. +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs index 780a510c500..a70ef31fed1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr new file mode 100644 index 00000000000..6d7980a9736 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<::Assoc as Foo>::foo` in constant functions + --> $DIR/assoc-type-const-bound-usage.rs:12:5 + | +LL | ::Assoc::foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index c350e3e4061..96ffca6519a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -1,21 +1,15 @@ -error[E0080]: evaluation of constant value failed - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: calling non-const function `<() as Tr>::a` - | -note: inside ` i32 {<() as Tr>::a} as FnOnce<((),)>>::call_once - shim(fn(()) -> i32 {<() as Tr>::a})` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL -note: inside `need_const_closure:: i32 {<() as Tr>::a}>` +error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closure-trait-method-fail.rs:15:5 | LL | x(()) | ^^^^^ -note: inside `_` - --> $DIR/const-closure-trait-method-fail.rs:18:23 | -LL | const _: () = assert!(need_const_closure(Tr::a) == 42); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs index 3e6d1908848..fd9f287250d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr new file mode 100644 index 00000000000..fd0c2911814 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs index 7c55b51c8f5..1fe4044d527 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr new file mode 100644 index 00000000000..abf2a2dc511 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -0,0 +1,39 @@ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:12:5 + | +LL | f() * 7 + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:5 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:11 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr index ce27e42f8c2..7de33003c48 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr @@ -1,3 +1,11 @@ +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/const-drop-fail-2.rs:25:9 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/const-drop-fail-2.rs:29:36 | @@ -6,6 +14,15 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/const-drop-fail-2.rs:39:9 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -For more information about this error, try `rustc --explain E0493`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 23e36887025..b28584e7e36 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -14,6 +14,15 @@ LL | let _ = S(&mut c); | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/const-drop.rs:70:13 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -For more information about this error, try `rustc --explain E0493`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 23e36887025..b28584e7e36 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -14,6 +14,15 @@ LL | let _ = S(&mut c); | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/const-drop.rs:70:13 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -For more information about this error, try `rustc --explain E0493`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs index 6ffdfa13132..f5644c8883d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs @@ -13,7 +13,7 @@ const fn foo() where T: ~const Tr {} pub trait Foo { fn foo() { foo::<()>(); - //FIXME ~^ ERROR the trait bound `(): ~const Tr` is not satisfied + //FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied } } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index fe51c1f1ca3..c21c73f40f2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): ~const Tr` is not satisfied +error[E0277]: the trait bound `(): Tr` is not satisfied --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | LL | ().a() - | ^ the trait `~const Tr` is not implemented for `()` + | ^ the trait `Tr` is not implemented for `()` | = help: the trait `Tr` is implemented for `()` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs index 0701cf93a02..3db59631ef8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -1,6 +1,7 @@ // Tests that trait bounds on specializing trait impls must be `~const` if the // same bound is present on the default impl and is `~const` there. -// known-bug: #110395 +// check-pass +// FIXME(effects) ^ should error #![feature(const_trait_impl)] #![feature(rustc_attrs)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr deleted file mode 100644 index 8f5ca2189da..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: missing `~const` qualifier for specialization - --> $DIR/const-default-bound-non-const-specialized-bound.rs:33:8 - | -LL | T: Foo, //FIXME ~ ERROR missing `~const` qualifier - | ^^^ - -error: missing `~const` qualifier for specialization - --> $DIR/const-default-bound-non-const-specialized-bound.rs:53:8 - | -LL | T: Foo, - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs index 9ddea427cfd..307d5a37bb0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -1,7 +1,8 @@ // Tests that a const default trait impl can be specialized by another const // trait impl and that the specializing impl will be used during const-eval. -// run-pass +// known-bug: #110395 +// FIXME run-pass #![feature(const_trait_impl)] #![feature(min_specialization)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr new file mode 100644 index 00000000000..6dad82b03b5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::value` in constant functions + --> $DIR/const-default-const-specialized.rs:16:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs index 35aa52fbd4e..f1fbbb512e3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs @@ -1,7 +1,7 @@ // Tests that a non-const default impl can be specialized by a const trait impl, // but that the default impl cannot be used in a const context. - -// run-pass +// known-bug: #110395 +// FIXME run-pass #![feature(const_trait_impl)] #![feature(min_specialization)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr new file mode 100644 index 00000000000..5ba4f2d52c5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::value` in constant functions + --> $DIR/non-const-default-const-specialized.rs:15:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs index 5c2a3f80170..0a28da9e65e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.rs @@ -22,7 +22,7 @@ impl const A for T { impl A for T { //~^ ERROR: cannot specialize -//~| ERROR: missing `~const` qualifier +//FIXME(effects) ~| ERROR: missing `~const` qualifier fn a() -> u32 { 3 } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr index 1ffdc50e589..08258fd1a57 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -4,11 +4,5 @@ error: cannot specialize on const impl with non-const impl LL | impl A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing `~const` qualifier for specialization - --> $DIR/specializing-constness.rs:23:9 - | -LL | impl A for T { - | ^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index fdc6b805889..2897eabb081 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,17 +1,17 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:16:24 + --> $DIR/super-traits-fail-3.rs:17:24 | LL | const fn foo(x: &T) { | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index 7375b8c819c..9839a4f2480 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,11 +1,11 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:12:19 + --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 8cf64944ac1..16c592830d7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -1,7 +1,8 @@ #![feature(const_trait_impl)] // revisions: yy yn ny nn -//[yy] check-pass +//[yy] known-bug: #110395 +//FIXME [yy] check-pass #[cfg_attr(any(yy, yn), const_trait)] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 7a152914b69..58225b94591 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,5 +1,5 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:16:24 + --> $DIR/super-traits-fail-3.rs:17:24 | LL | const fn foo(x: &T) { | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr new file mode 100644 index 00000000000..6bc643e6871 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/super-traits-fail-3.rs:19:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs index df96f6fb4ab..79cba548fd5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr new file mode 100644 index 00000000000..03d7b0549a6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/super-traits.rs:21:7 + | +LL | t.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs index 78a64b9018a..7338fb245b3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs @@ -24,6 +24,7 @@ impl const Add42 for () { fn bar(_: Foo) -> Foo<{ A::add(N) }> { //~^ ERROR `~const` is not allowed here + //~| ERROR cannot call Foo } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr index aae72f36e57..2a17ee3f372 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -10,5 +10,14 @@ note: this function is not `const`, so it cannot have `~const` trait bounds LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^ -error: aborting due to previous error +error[E0015]: cannot call non-const fn `::add` in constants + --> $DIR/tilde-const-and-const-params.rs:25:61 + | +LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs index 285cef571f3..411f4b2f68c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr new file mode 100644 index 00000000000..4b852b65b0c --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::foo` in constant functions + --> $DIR/tilde_const_on_impl_bound.rs:14:16 + | +LL | self.0.foo() + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs index 90e9afd8e52..47f7806e453 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs @@ -3,7 +3,7 @@ // (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a // test is not enough. // known-bug: #110395 -// check-pass +// FIXME check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr new file mode 100644 index 00000000000..54537231b61 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -0,0 +1,51 @@ +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/trait-where-clause-const.rs:20:5 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::b` in constant functions + --> $DIR/trait-where-clause-const.rs:21:5 + | +LL | T::b(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::c::` in constant functions + --> $DIR/trait-where-clause-const.rs:23:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::a` in constant functions + --> $DIR/trait-where-clause-const.rs:28:5 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::b` in constant functions + --> $DIR/trait-where-clause-const.rs:29:5 + | +LL | T::b(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `::c::` in constant functions + --> $DIR/trait-where-clause-const.rs:30:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs index 4b8b004069d..29809a2ee56 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -1,4 +1,5 @@ -// run-pass +// known-bug: #110395 +// FIXME run-pass #![feature(const_trait_impl)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr new file mode 100644 index 00000000000..b353c622b55 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::bar` in constant functions + --> $DIR/trait-where-clause-run.rs:14:9 + | +LL | ::bar() * 6 + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs index 3b028ac48db..32ebe03435d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -1,4 +1,5 @@ -// check-pass +// known-bug: #110395 +// FIXME check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr new file mode 100644 index 00000000000..7356fbd9267 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `::bar` in constant functions + --> $DIR/trait-where-clause-self-referential.rs:22:5 + | +LL | T::bar(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. From 1f960bc969ca6c05481da93b1a8ed060d37911b6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 2 Aug 2023 10:40:03 +0100 Subject: [PATCH 19/19] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index c91a693e797..020651c5225 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit c91a693e7977e33a1064b63a5daf5fb689f01651 +Subproject commit 020651c52257052d28f6fd83fbecf5cfa1ed516c