diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index f51b0086dc8b6..8730aeb0f3bff 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -52,7 +52,10 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { // when we try to compute the "horizontal trim". let lines = if kind == CommentKind::Block { // Whatever happens, we skip the first line. - let mut i = if lines[0].trim_start().starts_with('*') { 0 } else { 1 }; + let mut i = lines + .get(0) + .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 }) + .unwrap_or(0); let mut j = lines.len(); while i < j && lines[i].trim().is_empty() { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 28466315c8687..8340a0b360ef7 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -505,6 +505,8 @@ declare_features! ( (active, static_nobundle, "1.16.0", Some(37403), None), /// Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), + /// Allows lints part of the strict provenance effort. + (active, strict_provenance, "1.61.0", Some(95228), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5704c6ed3b25d..89ce307d12cd7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2648,6 +2648,96 @@ declare_lint! { }; } +declare_lint! { + /// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer + /// and a pointer. + /// + /// ### Example + /// + /// ```rust + /// #![feature(strict_provenance)] + /// #![warn(fuzzy_provenance_casts)] + /// + /// fn main() { + /// let _dangling = 16_usize as *const u8; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This lint is part of the strict provenance effort, see [issue #95228]. + /// Casting an integer to a pointer is considered bad style, as a pointer + /// contains, besides the *address* also a *provenance*, indicating what + /// memory the pointer is allowed to read/write. Casting an integer, which + /// doesn't have provenance, to a pointer requires the compiler to assign + /// (guess) provenance. The compiler assigns "all exposed valid" (see the + /// docs of [`ptr::from_exposed_addr`] for more information about this + /// "exposing"). This penalizes the optimiser and is not well suited for + /// dynamic analysis/dynamic program verification (e.g. Miri or CHERI + /// platforms). + /// + /// It is much better to use [`ptr::with_addr`] instead to specify the + /// provenance you want. If using this function is not possible because the + /// code relies on exposed provenance then there is as an escape hatch + /// [`ptr::from_exposed_addr`]. + /// + /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 + /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr + /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr + pub FUZZY_PROVENANCE_CASTS, + Allow, + "a fuzzy integer to pointer cast is used", + @feature_gate = sym::strict_provenance; +} + +declare_lint! { + /// The `lossy_provenance_casts` lint detects an `as` cast between a pointer + /// and an integer. + /// + /// ### Example + /// + /// ```rust + /// #![feature(strict_provenance)] + /// #![warn(lossy_provenance_casts)] + /// + /// fn main() { + /// let x: u8 = 37; + /// let _addr: usize = &x as *const u8 as usize; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This lint is part of the strict provenance effort, see [issue #95228]. + /// Casting a pointer to an integer is a lossy operation, because beyond + /// just an *address* a pointer may be associated with a particular + /// *provenance*. This information is used by the optimiser and for dynamic + /// analysis/dynamic program verification (e.g. Miri or CHERI platforms). + /// + /// Since this cast is lossy, it is considered good style to use the + /// [`ptr::addr`] method instead, which has a similar effect, but doesn't + /// "expose" the pointer provenance. This improves optimisation potential. + /// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information + /// about exposing pointer provenance. + /// + /// If your code can't comply with strict provenance and needs to expose + /// the provenance, then there is [`ptr::expose_addr`] as an escape hatch, + /// which preserves the behaviour of `as usize` casts while being explicit + /// about the semantics. + /// + /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228 + /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr + /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr + pub LOSSY_PROVENANCE_CASTS, + Allow, + "a lossy pointer to integer cast is used", + @feature_gate = sym::strict_provenance; +} + declare_lint! { /// The `const_evaluatable_unchecked` lint detects a generic constant used /// in a type. @@ -3101,6 +3191,8 @@ declare_lint_pass! { UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, CENUM_IMPL_DROP_CAST, + FUZZY_PROVENANCE_CASTS, + LOSSY_PROVENANCE_CASTS, CONST_EVALUATABLE_UNCHECKED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, MUST_NOT_SUSPEND, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f5803aaa0786e..dc4d10f699c75 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1348,6 +1348,7 @@ symbols! { str_trim, str_trim_end, str_trim_start, + strict_provenance, stringify, stringify_macro, struct_field_attributes, 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 9998c5bb087e1..ac98dd5801e40 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -36,6 +36,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use std::iter; +use std::ops::ControlFlow; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; @@ -2226,9 +2227,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { post.dedup(); if self.is_tainted_by_errors() - && crate_names.len() == 1 - && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) - && spans.len() == 0 + && (crate_names.len() == 1 + && spans.len() == 0 + && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str()) + || predicate.visit_with(&mut HasNumericInferVisitor).is_break()) { // Avoid complaining about other inference issues for expressions like // `42 >> 1`, where the types are still `{integer}`, but we want to @@ -2666,3 +2668,17 @@ impl ArgKind { } } } + +struct HasNumericInferVisitor; + +impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor { + type BreakTy = (); + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) { + ControlFlow::Break(()) + } else { + ControlFlow::CONTINUE + } + } +} diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 7ce428ea12466..6091b8fee00b6 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -807,11 +807,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { // ptr -> * (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast - (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast - (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), - // * -> ptr - (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast + // ptr-addr-cast + (Ptr(m_expr), Int(t_c)) => { + self.lossy_provenance_ptr2int_lint(fcx, t_c); + self.check_ptr_addr_cast(fcx, m_expr) + } + (FnPtr, Int(_)) => { + // FIXME(#95489): there should eventually be a lint for these casts + Ok(CastKind::FnPtrAddrCast) + } + // addr-ptr-cast + (Int(_), Ptr(mt)) => { + self.fuzzy_provenance_int2ptr_lint(fcx); + self.check_addr_ptr_cast(fcx, mt) + } + // fn-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), // prim -> prim @@ -973,6 +984,74 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } } + + fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::LOSSY_PROVENANCE_CASTS, + self.expr.hir_id, + self.span, + |err| { + let mut err = err.build(&format!( + "under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`", + self.expr_ty, self.cast_ty + )); + + let msg = "use `.addr()` to obtain the address of a pointer"; + if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { + let scalar_cast = match t_c { + ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(), + _ => format!(" as {}", self.cast_ty), + }; + err.span_suggestion( + self.span, + msg, + format!("({}).addr(){}", snippet, scalar_cast), + Applicability::MaybeIncorrect + ); + } else { + err.help(msg); + } + err.help( + "if you can't comply with strict provenance and need to expose the pointer\ + provenance you can use `.expose_addr()` instead" + ); + + err.emit(); + }, + ); + } + + fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::FUZZY_PROVENANCE_CASTS, + self.expr.hir_id, + self.span, + |err| { + + let mut err = err.build(&format!( + "strict provenance disallows casting integer `{}` to pointer `{}`", + self.expr_ty, self.cast_ty + )); + let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address"; + if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { + err.span_suggestion( + self.span, + msg, + format!("(...).with_addr({})", snippet), + Applicability::HasPlaceholders, + ); + } else { + err.help(msg); + } + err.help( + "if you can't comply with strict provenance and don't have a pointer with \ + the correct provenance you can use `std::ptr::from_exposed_addr()` instead" + ); + + err.emit(); + }, + ); + } } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index d8206e7893114..98fb7e9e41d7a 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -24,20 +24,30 @@ See also the macro [`compile_error!`], for raising errors during compilation. # When to use `panic!` vs `Result` -The Rust model of error handling groups errors into two major categories: -recoverable and unrecoverable errors. For a recoverable error, such as a file -not found error, it’s reasonable to report the problem to the user and retry -the operation. Unrecoverable errors are always symptoms of bugs, like trying to -access a location beyond the end of an array. +The Rust language provides two complementary systems for constructing / +representing, reporting, propagating, reacting to, and discarding errors. These +responsibilities are collectively known as "error handling." `panic!` and +`Result` are similar in that they are each the primary interface of their +respective error handling systems; however, the meaning these interfaces attach +to their errors and the responsibilities they fulfill within their respective +error handling systems differ. -The Rust language and standard library provides `Result` and `panic!` as parts -of two complementary systems for representing, reporting, propagating, reacting -to, and discarding errors for in these two categories. +The `panic!` macro is used to construct errors that represent a bug that has +been detected in your program. With `panic!` you provide a message that +describes the bug and the language then constructs an error with that message, +reports it, and propagates it for you. -The `panic!` macro is provided to represent unrecoverable errors, whereas the -`Result` enum is provided to represent recoverable errors. For more detailed -information about error handling check out the [book] or the [`std::result`] -module docs. +`Result` on the other hand is used to wrap other types that represent either +the successful result of some computation, `Ok(T)`, or error types that +represent an anticipated runtime failure mode of that computation, `Err(E)`. +`Result` is used alongside user defined types which represent the various +anticipated runtime failure modes that the associated computation could +encounter. `Result` must be propagated manually, often with the the help of the +`?` operator and `Try` trait, and they must be reported manually, often with +the help of the `Error` trait. + +For more detailed information about error handling check out the [book] or the +[`std::result`] module docs. [ounwrap]: Option::unwrap [runwrap]: Result::unwrap diff --git a/src/doc/unstable-book/src/language-features/strict-provenance.md b/src/doc/unstable-book/src/language-features/strict-provenance.md new file mode 100644 index 0000000000000..dc60f3f375d3c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/strict-provenance.md @@ -0,0 +1,22 @@ +# `strict_provenance` + +The tracking issue for this feature is: [#95228] + +[#95228]: https://github.com/rust-lang/rust/issues/95228 +----- + +The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. +These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. +The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). + +## Example + +```rust +#![feature(strict_provenance)] +#![warn(fuzzy_provenance_casts)] + +fn main() { + let _dangling = 16_usize as *const u8; + //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` +} +``` diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5c59609d5b8c6..228976cb171b5 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -371,7 +371,8 @@ crate fn print_where_clause<'a, 'tcx: 'a>( clause = clause.replace("
", &format!("
{}", padding)); clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); if !end_newline { - clause.insert_str(0, "
"); + // we insert the
after a single space but before multiple spaces at the start + clause.insert_str(if indent == 0 { 1 } else { 0 }, "
"); } } write!(f, "{}", clause) diff --git a/src/test/rustdoc/empty-doc-comment.rs b/src/test/rustdoc/empty-doc-comment.rs new file mode 100644 index 0000000000000..b1dae930e066b --- /dev/null +++ b/src/test/rustdoc/empty-doc-comment.rs @@ -0,0 +1,22 @@ +// Ensure that empty doc comments don't panic. + +/*! +*/ + +/// +/// +pub struct Foo; + +#[doc = " +"] +pub mod Mod { + //! + //! +} + +/** +*/ +pub mod Another { + #![doc = " +"] +} diff --git a/src/test/rustdoc/where.SWhere_Simd_item-decl.html b/src/test/rustdoc/where.SWhere_Simd_item-decl.html new file mode 100644 index 0000000000000..d941ad7de4c48 --- /dev/null +++ b/src/test/rustdoc/where.SWhere_Simd_item-decl.html @@ -0,0 +1 @@ +
pub struct Simd<T, const LANES: usize>(_) 
where
    T: Sized
;
\ No newline at end of file diff --git a/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html b/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html new file mode 100644 index 0000000000000..54026ff034e00 --- /dev/null +++ b/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html @@ -0,0 +1,3 @@ +
pub trait TraitWhere {
+    type Item<'a>
    where
        Self: 'a
; +}
\ No newline at end of file diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 549cfff96cb6d..73c75fdb61bcd 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -1,3 +1,4 @@ +#![feature(generic_associated_types)] #![crate_name = "foo"] pub trait MyTrait { fn dummy(&self) { } } @@ -19,6 +20,18 @@ impl Delta where D: MyTrait { pub struct Echo(E); +// @has 'foo/struct.Simd.html' +// @snapshot SWhere_Simd_item-decl - '//div[@class="docblock item-decl"]' +pub struct Simd([T; LANES]) +where + T: Sized; + +// @has 'foo/trait.TraitWhere.html' +// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="docblock item-decl"]' +pub trait TraitWhere { + type Item<'a> where Self: 'a; +} + // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // "impl MyTrait for Echo where E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.rs b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs new file mode 100644 index 0000000000000..75d0ee5700d07 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs @@ -0,0 +1,19 @@ +// check-pass + +#![deny(fuzzy_provenance_casts)] +//~^ WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +#![deny(lossy_provenance_casts)] +//~^ WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` + +fn main() { + // no warnings emitted since the lints are not activated + + let _dangling = 16_usize as *const u8; + + let x: u8 = 37; + let _addr: usize = &x as *const u8 as usize; +} diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr new file mode 100644 index 0000000000000..34bd240c304a7 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr @@ -0,0 +1,63 @@ +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: 6 warnings emitted + diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index a1cfee944c8bd..98fd13553c009 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -104,6 +104,32 @@ fn main() { "attempted to instantiate uninhabited type `Bar`" ); + test_panic_msg( + || mem::uninitialized::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Foo; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + + test_panic_msg( + || mem::uninitialized::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Bar; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + // Types that do not like zero-initialziation test_panic_msg( || mem::uninitialized::(), @@ -199,7 +225,9 @@ fn main() { let _val = mem::zeroed::(); let _val = mem::zeroed::>(); let _val = mem::zeroed::>>(); + let _val = mem::zeroed::<[!; 0]>(); let _val = mem::uninitialized::>(); + let _val = mem::uninitialized::<[!; 0]>(); // These are UB because they have not been officially blessed, but we await the resolution // of before doing diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs new file mode 100644 index 0000000000000..d2d72a68f1396 --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs @@ -0,0 +1,7 @@ +#![feature(strict_provenance)] +#![deny(fuzzy_provenance_casts)] + +fn main() { + let dangling = 16_usize as *const u8; + //~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8` +} diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr new file mode 100644 index 0000000000000..e50d243b6ad6d --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -0,0 +1,19 @@ +error: strict provenance disallows casting integer `usize` to pointer `*const u8` + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20 + | +LL | let dangling = 16_usize as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead +help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address + | +LL | let dangling = (...).with_addr(16_usize); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs new file mode 100644 index 0000000000000..3690fbc904d99 --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -0,0 +1,11 @@ +#![feature(strict_provenance)] +#![deny(lossy_provenance_casts)] + +fn main() { + let x: u8 = 37; + let addr: usize = &x as *const u8 as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + + let addr_32bit = &x as *const u8 as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` +} diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr new file mode 100644 index 0000000000000..489cb03ddd316 --- /dev/null +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -0,0 +1,23 @@ +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23 + | +LL | let addr: usize = &x as *const u8 as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()` + | +note: the lint level is defined here + --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 + | +LL | let addr_32bit = &x as *const u8 as u32; + | ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32` + | + = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/traits/no-fallback-multiple-impls.rs b/src/test/ui/traits/no-fallback-multiple-impls.rs new file mode 100644 index 0000000000000..7ed3796f08b76 --- /dev/null +++ b/src/test/ui/traits/no-fallback-multiple-impls.rs @@ -0,0 +1,16 @@ +trait Fallback { + fn foo(&self) {} +} + +impl Fallback for i32 {} + +impl Fallback for u64 {} + +impl Fallback for usize {} + +fn main() { + missing(); + //~^ ERROR cannot find function `missing` in this scope + 0.foo(); + // But then we shouldn't report an inference ambiguity here... +} diff --git a/src/test/ui/traits/no-fallback-multiple-impls.stderr b/src/test/ui/traits/no-fallback-multiple-impls.stderr new file mode 100644 index 0000000000000..61c9e5aaabdb4 --- /dev/null +++ b/src/test/ui/traits/no-fallback-multiple-impls.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/no-fallback-multiple-impls.rs:12:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs index d062de25ac8c1..342928e882a55 100644 --- a/src/test/ui/traits/test-2.rs +++ b/src/test/ui/traits/test-2.rs @@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } fn main() { - 10.dup::(); //~ ERROR type annotations needed + 10.dup::(); //~^ ERROR this associated function takes 0 generic arguments but 1 - 10.blah::(); //~ ERROR type annotations needed + 10.blah::(); //~^ ERROR this associated function takes 1 generic argument but 2 (Box::new(10) as Box).dup(); //~^ ERROR E0038 diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr index 5eec012458450..77ea4e4e974eb 100644 --- a/src/test/ui/traits/test-2.stderr +++ b/src/test/ui/traits/test-2.stderr @@ -79,35 +79,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = note: required because of the requirements on the impl of `CoerceUnsized>` for `Box<{integer}>` = note: required by cast to type `Box` -error[E0283]: type annotations needed - --> $DIR/test-2.rs:9:8 - | -LL | 10.dup::(); - | ^^^ cannot infer type for type `{integer}` - | -note: multiple `impl`s satisfying `{integer}: bar` found - --> $DIR/test-2.rs:5:1 - | -LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ -LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ - -error[E0283]: type annotations needed - --> $DIR/test-2.rs:11:8 - | -LL | 10.blah::(); - | ^^^^ cannot infer type for type `{integer}` - | -note: multiple `impl`s satisfying `{integer}: bar` found - --> $DIR/test-2.rs:5:1 - | -LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ -LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0038, E0107, E0283. +Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`.