Auto merge of #62635 - Centril:rollup-potvfnk, r=Centril
Rollup of 12 pull requests Successful merges: - #61535 (Coherence test when a generic type param has a default value from an associated type) - #62274 (rustc_mir: follow FalseUnwind's real_target edge in qualify_consts.) - #62431 (Add messages to `Option`'s and `Result`'s `must_use` annotation for `is_*`) - #62453 (in which we suggest anonymizing single-use lifetimes in paths ) - #62568 (Replace unsafe_destructor_blind_to_params with may_dangle) - #62578 (Add test for #49919) - #62595 (Document that the crate keyword refers to the project root) - #62599 (move mem::uninitialized deprecation back by 1 release, to 1.39) - #62605 (Emit dropped unemitted errors to aid in ICE debugging) - #62607 (Correctly break out of recovery loop) - #62608 (`async unsafe fn` tests) - #62623 (downgrade indirect_structural_match lint to allow) Failed merges: r? @ghost
This commit is contained in:
commit
e13fe7ff5e
69 changed files with 502 additions and 241 deletions
|
@ -62,7 +62,7 @@ Misc
|
||||||
Compatibility Notes
|
Compatibility Notes
|
||||||
-------------------
|
-------------------
|
||||||
- With the stabilisation of `mem::MaybeUninit`, `mem::uninitialized` use is no
|
- With the stabilisation of `mem::MaybeUninit`, `mem::uninitialized` use is no
|
||||||
longer recommended, and will be deprecated in 1.38.0.
|
longer recommended, and will be deprecated in 1.39.0.
|
||||||
|
|
||||||
[60318]: https://github.com/rust-lang/rust/pull/60318/
|
[60318]: https://github.com/rust-lang/rust/pull/60318/
|
||||||
[60364]: https://github.com/rust-lang/rust/pull/60364/
|
[60364]: https://github.com/rust-lang/rust/pull/60364/
|
||||||
|
|
|
@ -472,7 +472,7 @@ pub unsafe fn zeroed<T>() -> T {
|
||||||
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
|
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
|
||||||
/// [inv]: union.MaybeUninit.html#initialization-invariant
|
/// [inv]: union.MaybeUninit.html#initialization-invariant
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
|
#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub unsafe fn uninitialized<T>() -> T {
|
pub unsafe fn uninitialized<T>() -> T {
|
||||||
MaybeUninit::uninit().assume_init()
|
MaybeUninit::uninit().assume_init()
|
||||||
|
|
|
@ -178,7 +178,7 @@ impl<T> Option<T> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Some`]: #variant.Some
|
/// [`Some`]: #variant.Some
|
||||||
#[must_use]
|
#[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn is_some(&self) -> bool {
|
pub fn is_some(&self) -> bool {
|
||||||
|
@ -201,7 +201,8 @@ impl<T> Option<T> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`None`]: #variant.None
|
/// [`None`]: #variant.None
|
||||||
#[must_use]
|
#[must_use = "if you intended to assert that this doesn't have a value, consider \
|
||||||
|
`.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn is_none(&self) -> bool {
|
pub fn is_none(&self) -> bool {
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl<T, E> Result<T, E> {
|
||||||
/// let x: Result<i32, &str> = Err("Some error message");
|
/// let x: Result<i32, &str> = Err("Some error message");
|
||||||
/// assert_eq!(x.is_ok(), false);
|
/// assert_eq!(x.is_ok(), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn is_ok(&self) -> bool {
|
pub fn is_ok(&self) -> bool {
|
||||||
|
@ -302,7 +302,7 @@ impl<T, E> Result<T, E> {
|
||||||
/// let x: Result<i32, &str> = Err("Some error message");
|
/// let x: Result<i32, &str> = Err("Some error message");
|
||||||
/// assert_eq!(x.is_err(), true);
|
/// assert_eq!(x.is_err(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn is_err(&self) -> bool {
|
pub fn is_err(&self) -> bool {
|
||||||
|
|
|
@ -350,7 +350,8 @@ declare_lint! {
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub INDIRECT_STRUCTURAL_MATCH,
|
pub INDIRECT_STRUCTURAL_MATCH,
|
||||||
Warn,
|
// defaulting to allow until rust-lang/rust#62614 is fixed.
|
||||||
|
Allow,
|
||||||
"pattern with const indirectly referencing non-`#[structural_match]` type"
|
"pattern with const indirectly referencing non-`#[structural_match]` type"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +452,7 @@ declare_lint_pass! {
|
||||||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||||
NESTED_IMPL_TRAIT,
|
NESTED_IMPL_TRAIT,
|
||||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||||
|
INDIRECT_STRUCTURAL_MATCH,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::hir::def::{Res, DefKind};
|
||||||
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use crate::hir::map::Map;
|
use crate::hir::map::Map;
|
||||||
use crate::hir::ptr::P;
|
use crate::hir::ptr::P;
|
||||||
use crate::hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName};
|
use crate::hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName, QPath};
|
||||||
use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
|
use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
|
||||||
|
|
||||||
use crate::rustc::lint;
|
use crate::rustc::lint;
|
||||||
|
@ -1458,10 +1458,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper method to issue suggestions from `fn rah<'a>(&'a T)` to `fn rah(&T)`
|
// helper method to issue suggestions from `fn rah<'a>(&'a T)` to `fn rah(&T)`
|
||||||
|
// or from `fn rah<'a>(T<'a>)` to `fn rah(T<'_>)`
|
||||||
fn suggest_eliding_single_use_lifetime(
|
fn suggest_eliding_single_use_lifetime(
|
||||||
&self, err: &mut DiagnosticBuilder<'_>, def_id: DefId, lifetime: &hir::Lifetime
|
&self, err: &mut DiagnosticBuilder<'_>, def_id: DefId, lifetime: &hir::Lifetime
|
||||||
) {
|
) {
|
||||||
// FIXME: future work: also suggest `impl Foo<'_>` for `impl<'a> Foo<'a>`
|
|
||||||
let name = lifetime.name.ident();
|
let name = lifetime.name.ident();
|
||||||
let mut remove_decl = None;
|
let mut remove_decl = None;
|
||||||
if let Some(parent_def_id) = self.tcx.parent(def_id) {
|
if let Some(parent_def_id) = self.tcx.parent(def_id) {
|
||||||
|
@ -1471,18 +1471,38 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut remove_use = None;
|
let mut remove_use = None;
|
||||||
|
let mut elide_use = None;
|
||||||
let mut find_arg_use_span = |inputs: &hir::HirVec<hir::Ty>| {
|
let mut find_arg_use_span = |inputs: &hir::HirVec<hir::Ty>| {
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
if let hir::TyKind::Rptr(lt, _) = input.node {
|
match input.node {
|
||||||
if lt.name.ident() == name {
|
hir::TyKind::Rptr(lt, _) => {
|
||||||
// include the trailing whitespace between the ampersand and the type name
|
if lt.name.ident() == name {
|
||||||
let lt_through_ty_span = lifetime.span.to(input.span.shrink_to_hi());
|
// include the trailing whitespace between the lifetime and type names
|
||||||
remove_use = Some(
|
let lt_through_ty_span = lifetime.span.to(input.span.shrink_to_hi());
|
||||||
self.tcx.sess.source_map()
|
remove_use = Some(
|
||||||
.span_until_non_whitespace(lt_through_ty_span)
|
self.tcx.sess.source_map()
|
||||||
);
|
.span_until_non_whitespace(lt_through_ty_span)
|
||||||
break;
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
hir::TyKind::Path(ref qpath) => {
|
||||||
|
if let QPath::Resolved(_, path) = qpath {
|
||||||
|
|
||||||
|
let last_segment = &path.segments[path.segments.len()-1];
|
||||||
|
let generics = last_segment.generic_args();
|
||||||
|
for arg in generics.args.iter() {
|
||||||
|
if let GenericArg::Lifetime(lt) = arg {
|
||||||
|
if lt.name.ident() == name {
|
||||||
|
elide_use = Some(lt.span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1506,24 +1526,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (Some(decl_span), Some(use_span)) = (remove_decl, remove_use) {
|
let msg = "elide the single-use lifetime";
|
||||||
// if both declaration and use deletion spans start at the same
|
match (remove_decl, remove_use, elide_use) {
|
||||||
// place ("start at" because the latter includes trailing
|
(Some(decl_span), Some(use_span), None) => {
|
||||||
// whitespace), then this is an in-band lifetime
|
// if both declaration and use deletion spans start at the same
|
||||||
if decl_span.shrink_to_lo() == use_span.shrink_to_lo() {
|
// place ("start at" because the latter includes trailing
|
||||||
err.span_suggestion(
|
// whitespace), then this is an in-band lifetime
|
||||||
use_span,
|
if decl_span.shrink_to_lo() == use_span.shrink_to_lo() {
|
||||||
"elide the single-use lifetime",
|
err.span_suggestion(
|
||||||
String::new(),
|
use_span,
|
||||||
Applicability::MachineApplicable,
|
msg,
|
||||||
);
|
String::new(),
|
||||||
} else {
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.multipart_suggestion(
|
||||||
|
msg,
|
||||||
|
vec![(decl_span, String::new()), (use_span, String::new())],
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(decl_span), None, Some(use_span)) => {
|
||||||
err.multipart_suggestion(
|
err.multipart_suggestion(
|
||||||
"elide the single-use lifetime",
|
msg,
|
||||||
vec![(decl_span, String::new()), (use_span, String::new())],
|
vec![(decl_span, String::new()), (use_span, "'_".to_owned())],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ use rustc_macros::HashStable;
|
||||||
use std::{cmp, fmt};
|
use std::{cmp, fmt};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr::{self, SignedInt, UnsignedInt};
|
use syntax::attr::{self, SignedInt, UnsignedInt};
|
||||||
use syntax::symbol::sym;
|
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -435,20 +434,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
Some(dtor) => dtor.did
|
Some(dtor) => dtor.did
|
||||||
};
|
};
|
||||||
|
|
||||||
// RFC 1238: if the destructor method is tagged with the
|
|
||||||
// attribute `unsafe_destructor_blind_to_params`, then the
|
|
||||||
// compiler is being instructed to *assume* that the
|
|
||||||
// destructor will not access borrowed data,
|
|
||||||
// even if such data is otherwise reachable.
|
|
||||||
//
|
|
||||||
// Such access can be in plain sight (e.g., dereferencing
|
|
||||||
// `*foo.0` of `Foo<'a>(&'a u32)`) or indirectly hidden
|
|
||||||
// (e.g., calling `foo.0.clone()` of `Foo<T:Clone>`).
|
|
||||||
if self.has_attr(dtor, sym::unsafe_destructor_blind_to_params) {
|
|
||||||
debug!("destructor_constraint({:?}) - blind", def.did);
|
|
||||||
return vec![];
|
|
||||||
}
|
|
||||||
|
|
||||||
let impl_def_id = self.associated_item(dtor).container.id();
|
let impl_def_id = self.associated_item(dtor).container.id();
|
||||||
let impl_generics = self.generics_of(impl_def_id);
|
let impl_generics = self.generics_of(impl_def_id);
|
||||||
|
|
||||||
|
|
|
@ -380,10 +380,13 @@ impl<'a> Debug for DiagnosticBuilder<'a> {
|
||||||
impl<'a> Drop for DiagnosticBuilder<'a> {
|
impl<'a> Drop for DiagnosticBuilder<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !panicking() && !self.cancelled() {
|
if !panicking() && !self.cancelled() {
|
||||||
let mut db = DiagnosticBuilder::new(self.handler,
|
let mut db = DiagnosticBuilder::new(
|
||||||
Level::Bug,
|
self.handler,
|
||||||
"Error constructed but not emitted");
|
Level::Bug,
|
||||||
|
"the following error was constructed but not emitted",
|
||||||
|
);
|
||||||
db.emit();
|
db.emit();
|
||||||
|
self.emit();
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,6 +890,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
|
|
||||||
let target = match body[bb].terminator().kind {
|
let target = match body[bb].terminator().kind {
|
||||||
TerminatorKind::Goto { target } |
|
TerminatorKind::Goto { target } |
|
||||||
|
TerminatorKind::FalseUnwind { real_target: target, .. } |
|
||||||
TerminatorKind::Drop { target, .. } |
|
TerminatorKind::Drop { target, .. } |
|
||||||
TerminatorKind::DropAndReplace { target, .. } |
|
TerminatorKind::DropAndReplace { target, .. } |
|
||||||
TerminatorKind::Assert { target, .. } |
|
TerminatorKind::Assert { target, .. } |
|
||||||
|
@ -908,8 +909,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
TerminatorKind::GeneratorDrop |
|
TerminatorKind::GeneratorDrop |
|
||||||
TerminatorKind::Yield { .. } |
|
TerminatorKind::Yield { .. } |
|
||||||
TerminatorKind::Unreachable |
|
TerminatorKind::Unreachable |
|
||||||
TerminatorKind::FalseEdges { .. } |
|
TerminatorKind::FalseEdges { .. } => None,
|
||||||
TerminatorKind::FalseUnwind { .. } => None,
|
|
||||||
|
|
||||||
TerminatorKind::Return => {
|
TerminatorKind::Return => {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -246,7 +246,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
///
|
///
|
||||||
/// * (1.) `D` has a lifetime- or type-parametric Drop implementation,
|
/// * (1.) `D` has a lifetime- or type-parametric Drop implementation,
|
||||||
/// (where that `Drop` implementation does not opt-out of
|
/// (where that `Drop` implementation does not opt-out of
|
||||||
/// this check via the `unsafe_destructor_blind_to_params`
|
/// this check via the `may_dangle`
|
||||||
/// attribute), and
|
/// attribute), and
|
||||||
/// * (2.) the structure of `D` can reach a reference of type `&'a _`,
|
/// * (2.) the structure of `D` can reach a reference of type `&'a _`,
|
||||||
///
|
///
|
||||||
|
@ -279,7 +279,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
/// instead Drop-Check now simply assumes that if a destructor has
|
/// instead Drop-Check now simply assumes that if a destructor has
|
||||||
/// access (direct or indirect) to a lifetime parameter, then that
|
/// access (direct or indirect) to a lifetime parameter, then that
|
||||||
/// lifetime must be forced to outlive that destructor's dynamic
|
/// lifetime must be forced to outlive that destructor's dynamic
|
||||||
/// extent. We then provide the `unsafe_destructor_blind_to_params`
|
/// extent. We then provide the `may_dangle`
|
||||||
/// attribute as a way for destructor implementations to opt-out of
|
/// attribute as a way for destructor implementations to opt-out of
|
||||||
/// this conservative assumption (and thus assume the obligation of
|
/// this conservative assumption (and thus assume the obligation of
|
||||||
/// ensuring that they do not access data nor invoke methods of
|
/// ensuring that they do not access data nor invoke methods of
|
||||||
|
|
|
@ -3809,7 +3809,6 @@ const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[
|
||||||
sym::must_use,
|
sym::must_use,
|
||||||
sym::no_mangle,
|
sym::no_mangle,
|
||||||
sym::repr,
|
sym::repr,
|
||||||
sym::unsafe_destructor_blind_to_params,
|
|
||||||
sym::non_exhaustive
|
sym::non_exhaustive
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ mod continue_keyword { }
|
||||||
/// The `as` keyword can be used to change what the crate is referred to as in your project. If a
|
/// The `as` keyword can be used to change what the crate is referred to as in your project. If a
|
||||||
/// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores.
|
/// crate name includes a dash, it is implicitly imported with the dashes replaced by underscores.
|
||||||
///
|
///
|
||||||
/// `crate` is also used as in conjunction with `pub` to signify that the item it's attached to
|
/// `crate` can also be used as in conjunction with `pub` to signify that the item it's attached to
|
||||||
/// is public only to other members of the same crate it's in.
|
/// is public only to other members of the same crate it's in.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -131,6 +131,10 @@ mod continue_keyword { }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// `crate` is also used to represent the absolute path of a module, where `crate` refers to the
|
||||||
|
/// root of the current crate. For instance, `crate::foo::bar` refers to the name `bar` inside the
|
||||||
|
/// module `foo`, from anywhere else in the same crate.
|
||||||
|
///
|
||||||
/// [Reference]: ../reference/items/extern-crates.html
|
/// [Reference]: ../reference/items/extern-crates.html
|
||||||
mod crate_keyword { }
|
mod crate_keyword { }
|
||||||
|
|
||||||
|
|
|
@ -199,9 +199,6 @@ declare_features! (
|
||||||
|
|
||||||
// no-tracking-issue-end
|
// no-tracking-issue-end
|
||||||
|
|
||||||
// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
|
|
||||||
(active, dropck_parametricity, "1.3.0", Some(28498), None),
|
|
||||||
|
|
||||||
// no-tracking-issue-start
|
// no-tracking-issue-start
|
||||||
|
|
||||||
// Allows using `#[omit_gdb_pretty_printer_section]`.
|
// Allows using `#[omit_gdb_pretty_printer_section]`.
|
||||||
|
@ -641,6 +638,8 @@ declare_features! (
|
||||||
(removed, extern_in_paths, "1.33.0", Some(55600), None,
|
(removed, extern_in_paths, "1.33.0", Some(55600), None,
|
||||||
Some("subsumed by `::foo::bar` paths")),
|
Some("subsumed by `::foo::bar` paths")),
|
||||||
(removed, quote, "1.33.0", Some(29601), None, None),
|
(removed, quote, "1.33.0", Some(29601), None, None),
|
||||||
|
// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
|
||||||
|
(removed, dropck_parametricity, "1.38.0", Some(28498), None, None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: removed features
|
// feature-group-end: removed features
|
||||||
|
@ -1447,15 +1446,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
cfg_fn!(omit_gdb_pretty_printer_section)
|
cfg_fn!(omit_gdb_pretty_printer_section)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
(sym::unsafe_destructor_blind_to_params,
|
|
||||||
Normal,
|
|
||||||
template!(Word),
|
|
||||||
Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761",
|
|
||||||
Some("replace this attribute with `#[may_dangle]`")),
|
|
||||||
sym::dropck_parametricity,
|
|
||||||
"unsafe_destructor_blind_to_params has been replaced by \
|
|
||||||
may_dangle and will be removed in the future",
|
|
||||||
cfg_fn!(dropck_parametricity))),
|
|
||||||
(sym::may_dangle,
|
(sym::may_dangle,
|
||||||
Normal,
|
Normal,
|
||||||
template!(Word),
|
template!(Word),
|
||||||
|
|
|
@ -4629,6 +4629,9 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
|
fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> {
|
||||||
let mut stmts = vec![];
|
let mut stmts = vec![];
|
||||||
while !self.eat(&token::CloseDelim(token::Brace)) {
|
while !self.eat(&token::CloseDelim(token::Brace)) {
|
||||||
|
if self.token == token::Eof {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let stmt = match self.parse_full_stmt(false) {
|
let stmt = match self.parse_full_stmt(false) {
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -4643,8 +4646,6 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
if let Some(stmt) = stmt {
|
if let Some(stmt) = stmt {
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
} else if self.token == token::Eof {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
// Found only `;` or `}`.
|
// Found only `;` or `}`.
|
||||||
continue;
|
continue;
|
||||||
|
@ -6666,12 +6667,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a module from a source file.
|
/// Reads a module from a source file.
|
||||||
fn eval_src_mod(&mut self,
|
fn eval_src_mod(
|
||||||
path: PathBuf,
|
&mut self,
|
||||||
directory_ownership: DirectoryOwnership,
|
path: PathBuf,
|
||||||
name: String,
|
directory_ownership: DirectoryOwnership,
|
||||||
id_sp: Span)
|
name: String,
|
||||||
-> PResult<'a, (ast::Mod, Vec<Attribute> )> {
|
id_sp: Span,
|
||||||
|
) -> PResult<'a, (ast::Mod, Vec<Attribute>)> {
|
||||||
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
|
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
|
||||||
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
|
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
|
||||||
let mut err = String::from("circular modules: ");
|
let mut err = String::from("circular modules: ");
|
||||||
|
|
|
@ -34,7 +34,7 @@ fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return a crate.
|
/// Parse a string, return a crate.
|
||||||
pub fn string_to_crate (source_str : String) -> ast::Crate {
|
pub fn string_to_crate(source_str : String) -> ast::Crate {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
p.parse_crate_mod()
|
p.parse_crate_mod()
|
||||||
|
@ -42,7 +42,7 @@ pub fn string_to_crate (source_str : String) -> ast::Crate {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return an expr
|
/// Parse a string, return an expr
|
||||||
pub fn string_to_expr (source_str : String) -> P<ast::Expr> {
|
pub fn string_to_expr(source_str : String) -> P<ast::Expr> {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
p.parse_expr()
|
p.parse_expr()
|
||||||
|
@ -50,7 +50,7 @@ pub fn string_to_expr (source_str : String) -> P<ast::Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return an item
|
/// Parse a string, return an item
|
||||||
pub fn string_to_item (source_str : String) -> Option<P<ast::Item>> {
|
pub fn string_to_item(source_str : String) -> Option<P<ast::Item>> {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
p.parse_item()
|
p.parse_item()
|
||||||
|
|
|
@ -695,7 +695,6 @@ symbols! {
|
||||||
unmarked_api,
|
unmarked_api,
|
||||||
unreachable_code,
|
unreachable_code,
|
||||||
unrestricted_attribute_tokens,
|
unrestricted_attribute_tokens,
|
||||||
unsafe_destructor_blind_to_params,
|
|
||||||
unsafe_no_drop_flag,
|
unsafe_no_drop_flag,
|
||||||
unsized_locals,
|
unsized_locals,
|
||||||
unsized_tuple_coercion,
|
unsized_tuple_coercion,
|
||||||
|
|
|
@ -6,6 +6,7 @@ const fn f(x: usize) -> usize {
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
for i in 0..x {
|
for i in 0..x {
|
||||||
//~^ ERROR E0015
|
//~^ ERROR E0015
|
||||||
|
//~| ERROR E0017
|
||||||
//~| ERROR E0019
|
//~| ERROR E0019
|
||||||
//~| ERROR E0019
|
//~| ERROR E0019
|
||||||
//~| ERROR E0080
|
//~| ERROR E0080
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
[(); & { loop { continue } } ]; //~ ERROR mismatched types
|
[(); & { loop { continue } } ]; //~ ERROR mismatched types
|
||||||
[(); loop { break }]; //~ ERROR mismatched types
|
[(); loop { break }]; //~ ERROR mismatched types
|
||||||
[(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type
|
[(); {while true {break}; 0}];
|
||||||
//~^ WARN denote infinite loops with
|
|
||||||
[(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions
|
|
||||||
//~^ ERROR constant contains unimplemented expression type
|
//~^ ERROR constant contains unimplemented expression type
|
||||||
//~| ERROR constant contains unimplemented expression type
|
//~| ERROR constant contains unimplemented expression type
|
||||||
|
//~| WARN denote infinite loops with
|
||||||
|
[(); { for _ in 0usize.. {}; 0}];
|
||||||
|
//~^ ERROR calls in constants are limited to constant functions
|
||||||
|
//~| ERROR references in constants may only refer to immutable values
|
||||||
|
//~| ERROR constant contains unimplemented expression type
|
||||||
|
//~| ERROR constant contains unimplemented expression type
|
||||||
//~| ERROR evaluation of constant value failed
|
//~| ERROR evaluation of constant value failed
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,3 +20,12 @@ pub struct BatchInsert<'a, T: 'a, Tab> {
|
||||||
impl<'a, T:'a, Tab, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
|
impl<'a, T:'a, Tab, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
|
||||||
where DB: SupportsDefaultKeyword + Backend,
|
where DB: SupportsDefaultKeyword + Backend,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
pub trait LibToOwned {
|
||||||
|
type Owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LibCow<T: LibToOwned, Owned = <T as LibToOwned>::Owned> {
|
||||||
|
pub t: T,
|
||||||
|
pub o: Owned,
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// run-pass
|
||||||
|
// aux-build:re_rebalance_coherence_lib.rs
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![feature(re_rebalance_coherence)]
|
||||||
|
// check that a generic type with a default value from an associated type can be used without
|
||||||
|
// specifying the value, and without invoking coherence errors.
|
||||||
|
|
||||||
|
extern crate re_rebalance_coherence_lib as lib;
|
||||||
|
use lib::*;
|
||||||
|
|
||||||
|
struct MyString {}
|
||||||
|
|
||||||
|
impl LibToOwned for MyString {
|
||||||
|
type Owned = String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<MyString> for LibCow<MyString> {
|
||||||
|
fn eq(&self, _other: &MyString) -> bool {
|
||||||
|
// Test that the default type is used.
|
||||||
|
let _s: &String = &self.o;
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -1,12 +1,11 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
// Check that item-less traits do not cause dropck to inject extra
|
// Check that item-less traits do not cause dropck to inject extra
|
||||||
// region constraints.
|
// region constraints.
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
||||||
trait UserDefined { }
|
trait UserDefined { }
|
||||||
|
|
||||||
|
@ -20,9 +19,8 @@ impl<'a, T> UserDefined for &'a T { }
|
||||||
// ```
|
// ```
|
||||||
macro_rules! impl_drop {
|
macro_rules! impl_drop {
|
||||||
($Bound:ident, $Id:ident) => {
|
($Bound:ident, $Id:ident) => {
|
||||||
struct $Id<T:$Bound>(T);
|
struct $Id<T: $Bound>(T);
|
||||||
impl <T:$Bound> Drop for $Id<T> {
|
unsafe impl <#[may_dangle] T: $Bound> Drop for $Id<T> {
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
fn drop(&mut self) { }
|
fn drop(&mut self) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(deprecated)] // FIXME: switch to `#[may_dangle]` below.
|
|
||||||
|
|
||||||
// Example taken from RFC 1238 text
|
// Example taken from RFC 1238 text
|
||||||
|
|
||||||
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
|
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
|
||||||
// #example-of-the-unguarded-escape-hatch
|
// #example-of-the-unguarded-escape-hatch
|
||||||
|
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_eyepatch)]
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
|
struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
|
||||||
|
|
||||||
struct Foo<T> { data: Vec<T> }
|
struct Foo<T> { data: Vec<T> }
|
||||||
|
|
||||||
impl<T> Drop for Foo<T> {
|
// Below is the UGEH attribute
|
||||||
// Below is the UGEH attribute
|
unsafe impl<#[may_dangle] T> Drop for Foo<T> {
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
fn drop(&mut self) { }
|
fn drop(&mut self) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(deprecated)] // FIXME: switch to `#[may_dangle]` below.
|
|
||||||
|
|
||||||
// Demonstrate the use of the unguarded escape hatch with a lifetime param
|
// Demonstrate the use of the unguarded escape hatch with a lifetime param
|
||||||
// to assert that destructor will not access any dead data.
|
// to assert that destructor will not access any dead data.
|
||||||
//
|
//
|
||||||
// Compare with compile-fail/issue28498-reject-lifetime-param.rs
|
// Compare with compile-fail/issue28498-reject-lifetime-param.rs
|
||||||
|
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ScribbleOnDrop(String);
|
struct ScribbleOnDrop(String);
|
||||||
|
@ -19,11 +18,9 @@ impl Drop for ScribbleOnDrop {
|
||||||
|
|
||||||
struct Foo<'a>(u32, &'a ScribbleOnDrop);
|
struct Foo<'a>(u32, &'a ScribbleOnDrop);
|
||||||
|
|
||||||
impl<'a> Drop for Foo<'a> {
|
unsafe impl<#[may_dangle] 'a> Drop for Foo<'a> {
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is sound,
|
// Use of `may_dangle` is sound, because destructor never accesses `self.1`.
|
||||||
// because destructor never accesses `self.1`.
|
|
||||||
println!("Dropping Foo({}, _)", self.0);
|
println!("Dropping Foo({}, _)", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(deprecated)] // FIXME: switch to `#[may_dangle]` below.
|
|
||||||
|
|
||||||
// Demonstrate the use of the unguarded escape hatch with a type param in negative position
|
// Demonstrate the use of the unguarded escape hatch with a type param in negative position
|
||||||
// to assert that destructor will not access any dead data.
|
// to assert that destructor will not access any dead data.
|
||||||
|
@ -11,7 +10,7 @@
|
||||||
//
|
//
|
||||||
// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
|
// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
|
||||||
|
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ScribbleOnDrop(String);
|
struct ScribbleOnDrop(String);
|
||||||
|
@ -24,12 +23,10 @@ impl Drop for ScribbleOnDrop {
|
||||||
|
|
||||||
struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
|
struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
|
||||||
|
|
||||||
impl<T> Drop for Foo<T> {
|
unsafe impl<#[may_dangle] T> Drop for Foo<T> {
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is sound,
|
// Use of `may_dangle` is sound, because destructor never passes a `self.1`
|
||||||
// because destructor never passes a `self.1` to the callback
|
// to the callback (in `self.2`) despite having it available.
|
||||||
// (in `self.2`) despite having it available.
|
|
||||||
println!("Dropping Foo({}, _)", self.0);
|
println!("Dropping Foo({}, _)", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(deprecated)] // FIXME: switch to `#[may_dangle]` below.
|
|
||||||
|
|
||||||
// Demonstrate the use of the unguarded escape hatch with a trait bound
|
// Demonstrate the use of the unguarded escape hatch with a trait bound
|
||||||
// to assert that destructor will not access any dead data.
|
// to assert that destructor will not access any dead data.
|
||||||
//
|
//
|
||||||
// Compare with compile-fail/issue28498-reject-trait-bound.rs
|
// Compare with compile-fail/issue28498-reject-trait-bound.rs
|
||||||
|
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -19,14 +18,12 @@ impl Drop for ScribbleOnDrop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo<T:fmt::Debug>(u32, T);
|
struct Foo<T: fmt::Debug>(u32, T);
|
||||||
|
|
||||||
impl<T:fmt::Debug> Drop for Foo<T> {
|
unsafe impl<#[may_dangle] T: fmt::Debug> Drop for Foo<T> {
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is sound,
|
// Use of `may_dangle` is sound, because destructor never accesses
|
||||||
// because destructor never accesses the `Debug::fmt` method
|
// the `Debug::fmt` method of `T`, despite having it available.
|
||||||
// of `T`, despite having it available.
|
|
||||||
println!("Dropping Foo({}, _)", self.0);
|
println!("Dropping Foo({}, _)", self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// see async-closure.rs for async_closure + async_closure_in_unsafe_block
|
||||||
|
|
||||||
async fn async_fn(x: u8) -> u8 {
|
async fn async_fn(x: u8) -> u8 {
|
||||||
wake_and_yield_once().await;
|
wake_and_yield_once().await;
|
||||||
x
|
x
|
||||||
|
@ -120,6 +122,18 @@ async unsafe fn unsafe_async_fn(x: u8) -> u8 {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn unsafe_fn(x: u8) -> u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_block_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
|
||||||
|
unsafe {
|
||||||
|
async move {
|
||||||
|
unsafe_fn(unsafe_async_fn(x).await)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
|
@ -176,6 +190,7 @@ fn main() {
|
||||||
async_fn,
|
async_fn,
|
||||||
generic_async_fn,
|
generic_async_fn,
|
||||||
async_fn_with_internal_borrow,
|
async_fn_with_internal_borrow,
|
||||||
|
async_block_in_unsafe_block,
|
||||||
Foo::async_assoc_item,
|
Foo::async_assoc_item,
|
||||||
|x| {
|
|x| {
|
||||||
async move {
|
async move {
|
||||||
|
|
|
@ -53,6 +53,21 @@ fn async_closure(x: u8) -> impl Future<Output = u8> {
|
||||||
})(x)
|
})(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn async_closure_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
|
||||||
|
(unsafe {
|
||||||
|
async move |x: u8| unsafe_fn(unsafe_async_fn(x).await)
|
||||||
|
})(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
async unsafe fn unsafe_async_fn(x: u8) -> u8 {
|
||||||
|
wake_and_yield_once().await;
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn unsafe_fn(x: u8) -> u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(u8) -> Fut,
|
F: FnOnce(u8) -> Fut,
|
||||||
|
@ -77,5 +92,6 @@ fn main() {
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
async_closure,
|
async_closure,
|
||||||
|
async_closure_in_unsafe_block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs
Normal file
21
src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
async unsafe fn f() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
async unsafe fn f() {}
|
||||||
|
|
||||||
|
async fn g() {
|
||||||
|
S::f(); //~ ERROR call to unsafe function is unsafe
|
||||||
|
f(); //~ ERROR call to unsafe function is unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
S::f(); //~ ERROR call to unsafe function is unsafe
|
||||||
|
f(); //~ ERROR call to unsafe function is unsafe
|
||||||
|
}
|
35
src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr
Normal file
35
src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/async-unsafe-fn-call-in-safe.rs:14:5
|
||||||
|
|
|
||||||
|
LL | S::f();
|
||||||
|
| ^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/async-unsafe-fn-call-in-safe.rs:15:5
|
||||||
|
|
|
||||||
|
LL | f();
|
||||||
|
| ^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/async-unsafe-fn-call-in-safe.rs:19:5
|
||||||
|
|
|
||||||
|
LL | S::f();
|
||||||
|
| ^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/async-unsafe-fn-call-in-safe.rs:20:5
|
||||||
|
|
|
||||||
|
LL | f();
|
||||||
|
| ^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
|
@ -77,6 +77,12 @@ fn async_closure(x: u8) -> impl Future<Output = u8> {
|
||||||
})(x)
|
})(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn async_closure_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
|
||||||
|
(unsafe {
|
||||||
|
async move |x: u8| unsafe_fn(await!(unsafe_async_fn(x)))
|
||||||
|
})(x)
|
||||||
|
}
|
||||||
|
|
||||||
async fn async_fn(x: u8) -> u8 {
|
async fn async_fn(x: u8) -> u8 {
|
||||||
await!(wake_and_yield_once());
|
await!(wake_and_yield_once());
|
||||||
x
|
x
|
||||||
|
@ -127,6 +133,18 @@ async unsafe fn unsafe_async_fn(x: u8) -> u8 {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn unsafe_fn(x: u8) -> u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_block_in_unsafe_block(x: u8) -> impl Future<Output = u8> {
|
||||||
|
unsafe {
|
||||||
|
async move {
|
||||||
|
unsafe_fn(await!(unsafe_async_fn(x)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
|
@ -134,11 +152,15 @@ trait Bar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
async fn async_method(x: u8) -> u8 {
|
async fn async_assoc_item(x: u8) -> u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
await!(unsafe_async_fn(x))
|
await!(unsafe_async_fn(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
|
||||||
|
await!(unsafe_async_fn(x))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
||||||
|
@ -177,15 +199,22 @@ fn main() {
|
||||||
async_block,
|
async_block,
|
||||||
async_nonmove_block,
|
async_nonmove_block,
|
||||||
async_closure,
|
async_closure,
|
||||||
|
async_closure_in_unsafe_block,
|
||||||
async_fn,
|
async_fn,
|
||||||
generic_async_fn,
|
generic_async_fn,
|
||||||
async_fn_with_internal_borrow,
|
async_fn_with_internal_borrow,
|
||||||
Foo::async_method,
|
async_block_in_unsafe_block,
|
||||||
|
Foo::async_assoc_item,
|
||||||
|x| {
|
|x| {
|
||||||
async move {
|
async move {
|
||||||
unsafe { await!(unsafe_async_fn(x)) }
|
unsafe { await!(unsafe_async_fn(x)) }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|x| {
|
||||||
|
async move {
|
||||||
|
unsafe { await!(Foo::async_unsafe_assoc_item(x)) }
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
test_with_borrow! {
|
test_with_borrow! {
|
||||||
async_block_with_borrow_named_lifetime,
|
async_block_with_borrow_named_lifetime,
|
||||||
|
|
|
@ -4,7 +4,9 @@ fn main() {
|
||||||
let _ = [(); {
|
let _ = [(); {
|
||||||
//~^ WARNING Constant evaluating a complex constant, this might take some time
|
//~^ WARNING Constant evaluating a complex constant, this might take some time
|
||||||
let mut n = 113383; // #20 in https://oeis.org/A006884
|
let mut n = 113383; // #20 in https://oeis.org/A006884
|
||||||
while n != 0 { //~ ERROR constant contains unimplemented expression type
|
while n != 0 {
|
||||||
|
//~^ ERROR constant contains unimplemented expression type
|
||||||
|
//~| ERROR constant contains unimplemented expression type
|
||||||
n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
||||||
//~^ ERROR evaluation of constant value failed
|
//~^ ERROR evaluation of constant value failed
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
|
error[E0019]: constant contains unimplemented expression type
|
||||||
|
--> $DIR/infinite_loop.rs:7:15
|
||||||
|
|
|
||||||
|
LL | while n != 0 {
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0019]: constant contains unimplemented expression type
|
error[E0019]: constant contains unimplemented expression type
|
||||||
--> $DIR/infinite_loop.rs:7:9
|
--> $DIR/infinite_loop.rs:7:9
|
||||||
|
|
|
|
||||||
LL | / while n != 0 {
|
LL | / while n != 0 {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
LL | | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
LL | | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
||||||
LL | |
|
LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
|
@ -21,12 +29,12 @@ LL | | }];
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/infinite_loop.rs:8:20
|
--> $DIR/infinite_loop.rs:10:20
|
||||||
|
|
|
|
||||||
LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
|
||||||
| ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
|
| ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0019, E0080.
|
Some errors have detailed explanations: E0019, E0080.
|
||||||
For more information about an error, try `rustc --explain E0019`.
|
For more information about an error, try `rustc --explain E0019`.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
[(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
|
[(); { &loop { break } as *const _ as usize } ];
|
||||||
//~^ ERROR it is undefined behavior to use this value
|
//~^ ERROR casting pointers to integers in constants is unstable
|
||||||
|
//~| ERROR it is undefined behavior to use this value
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
error[E0019]: constant contains unimplemented expression type
|
error[E0658]: casting pointers to integers in constants is unstable
|
||||||
--> $DIR/issue-52442.rs:2:14
|
--> $DIR/issue-52442.rs:2:13
|
||||||
|
|
|
|
||||||
LL | [(); { &loop { break } as *const _ as usize } ];
|
LL | [(); { &loop { break } as *const _ as usize } ];
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/51910
|
||||||
|
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error[E0080]: it is undefined behavior to use this value
|
||||||
--> $DIR/issue-52442.rs:2:11
|
--> $DIR/issue-52442.rs:2:11
|
||||||
|
@ -14,5 +17,5 @@ LL | [(); { &loop { break } as *const _ as usize } ];
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0019, E0080.
|
Some errors have detailed explanations: E0080, E0658.
|
||||||
For more information about an error, try `rustc --explain E0019`.
|
For more information about an error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -3,7 +3,9 @@ fn main() {
|
||||||
//~^ WARNING Constant evaluating a complex constant, this might take some time
|
//~^ WARNING Constant evaluating a complex constant, this might take some time
|
||||||
let mut x = &0;
|
let mut x = &0;
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
while n < 5 { //~ ERROR constant contains unimplemented expression type
|
while n < 5 {
|
||||||
|
//~^ ERROR constant contains unimplemented expression type
|
||||||
|
//~| ERROR constant contains unimplemented expression type
|
||||||
n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
|
n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
|
||||||
x = &0; // Materialize a new AllocId
|
x = &0; // Materialize a new AllocId
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
|
error[E0019]: constant contains unimplemented expression type
|
||||||
|
--> $DIR/issue-52475.rs:6:15
|
||||||
|
|
|
||||||
|
LL | while n < 5 {
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
error[E0019]: constant contains unimplemented expression type
|
error[E0019]: constant contains unimplemented expression type
|
||||||
--> $DIR/issue-52475.rs:6:9
|
--> $DIR/issue-52475.rs:6:9
|
||||||
|
|
|
|
||||||
LL | / while n < 5 {
|
LL | / while n < 5 {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
LL | | n = (n + 1) % 5;
|
LL | | n = (n + 1) % 5;
|
||||||
LL | | x = &0; // Materialize a new AllocId
|
LL | | x = &0; // Materialize a new AllocId
|
||||||
LL | | }
|
LL | | }
|
||||||
|
@ -21,12 +29,12 @@ LL | | }];
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/issue-52475.rs:7:17
|
--> $DIR/issue-52475.rs:9:17
|
||||||
|
|
|
|
||||||
LL | n = (n + 1) % 5;
|
LL | n = (n + 1) % 5;
|
||||||
| ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
|
| ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0019, E0080.
|
Some errors have detailed explanations: E0019, E0080.
|
||||||
For more information about an error, try `rustc --explain E0019`.
|
For more information about an error, try `rustc --explain E0019`.
|
||||||
|
|
9
src/test/ui/consts/const-eval/issue-62272.rs
Normal file
9
src/test/ui/consts/const-eval/issue-62272.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
// Tests that `loop`s unconditionally-broken-from are allowed in constants.
|
||||||
|
|
||||||
|
const FOO: () = loop { break; };
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
[FOO; { let x; loop { x = 5; break; } x }];
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
// Using labeled break in a while loop has caused an illegal instruction being
|
// Using labeled break in a while loop has caused an illegal instruction being
|
||||||
// generated, and an ICE later.
|
// generated, and an ICE later.
|
||||||
//
|
//
|
||||||
// See https://github.com/rust-lang/rust/issues/51350 for more information.
|
// See https://github.com/rust-lang/rust/issues/51350 for more information.
|
||||||
|
|
||||||
const CRASH: () = 'a: while break 'a {};
|
const CRASH: () = 'a: while break 'a {};
|
||||||
//~^ ERROR constant contains unimplemented expression type
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
error[E0019]: constant contains unimplemented expression type
|
|
||||||
--> $DIR/const-labeled-break.rs:6:19
|
|
||||||
|
|
|
||||||
LL | const CRASH: () = 'a: while break 'a {};
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0019`.
|
|
|
@ -1,12 +0,0 @@
|
||||||
#![deny(deprecated)]
|
|
||||||
#![feature(dropck_parametricity)]
|
|
||||||
|
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
impl Drop for Foo {
|
|
||||||
#[unsafe_destructor_blind_to_params]
|
|
||||||
//~^ ERROR use of deprecated attribute `dropck_parametricity`
|
|
||||||
fn drop(&mut self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,14 +0,0 @@
|
||||||
error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
|
|
||||||
--> $DIR/feature-gate-dropck-ugeh-2.rs:7:5
|
|
||||||
|
|
|
||||||
LL | #[unsafe_destructor_blind_to_params]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
|
|
||||||
|
|
|
||||||
note: lint level defined here
|
|
||||||
--> $DIR/feature-gate-dropck-ugeh-2.rs:1:9
|
|
||||||
|
|
|
||||||
LL | #![deny(deprecated)]
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
// gate-test-dropck_parametricity
|
|
||||||
|
|
||||||
// Ensure that attempts to use the unsafe attribute are feature-gated.
|
|
||||||
// Example adapted from RFC 1238 text (just left out the feature gate).
|
|
||||||
|
|
||||||
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
|
|
||||||
// #example-of-the-unguarded-escape-hatch
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
|
|
||||||
struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
|
|
||||||
|
|
||||||
struct Foo<T> { data: Vec<T> }
|
|
||||||
|
|
||||||
impl<T> Drop for Foo<T> {
|
|
||||||
#[unsafe_destructor_blind_to_params] // This is the UGEH attribute
|
|
||||||
//~^ ERROR unsafe_destructor_blind_to_params has been replaced
|
|
||||||
//~| WARN use of deprecated attribute `dropck_parametricity`
|
|
||||||
fn drop(&mut self) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut foo = Foo { data: Vec::new() };
|
|
||||||
foo.data.push(Concrete(0, Cell::new(None)));
|
|
||||||
foo.data.push(Concrete(0, Cell::new(None)));
|
|
||||||
|
|
||||||
foo.data[0].1.set(Some(&foo.data[1]));
|
|
||||||
foo.data[1].1.set(Some(&foo.data[0]));
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
error[E0658]: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future
|
|
||||||
--> $DIR/feature-gate-dropck-ugeh.rs:16:5
|
|
||||||
|
|
|
||||||
LL | #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/28498
|
|
||||||
= help: add `#![feature(dropck_parametricity)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
warning: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
|
|
||||||
--> $DIR/feature-gate-dropck-ugeh.rs:16:5
|
|
||||||
|
|
|
||||||
LL | #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this attribute with `#[may_dangle]`
|
|
||||||
|
|
|
||||||
= note: #[warn(deprecated)] on by default
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
7
src/test/ui/issues/issue-49919.rs
Normal file
7
src/test/ui/issues/issue-49919.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
fn foo<'a, T: 'a>(t: T) -> Box<dyn Fn() -> &'a T + 'a> {
|
||||||
|
let foo: Box<dyn for <'c> Fn() -> &'c T> = Box::new(move || &t);
|
||||||
|
//~^ ERROR: binding for associated type
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
9
src/test/ui/issues/issue-49919.stderr
Normal file
9
src/test/ui/issues/issue-49919.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0582]: binding for associated type `Output` references lifetime `'c`, which does not appear in the trait input types
|
||||||
|
--> $DIR/issue-49919.rs:2:39
|
||||||
|
|
|
||||||
|
LL | let foo: Box<dyn for <'c> Fn() -> &'c T> = Box::new(move || &t);
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0582`.
|
|
@ -1,5 +1,5 @@
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
trait Foo<'a> {
|
trait Foo<'a> {
|
||||||
const C: Option<Cell<&'a u32>>;
|
const C: Option<Cell<&'a u32>>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `std::cell::Cell` in a pattern, `std::cell::C
|
||||||
LL | <() as Foo<'static>>::C => { }
|
LL | <() as Foo<'static>>::C => { }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/issue-55511.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
3
src/test/ui/issues/issue-61858.rs
Normal file
3
src/test/ui/issues/issue-61858.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
(if foobar) //~ ERROR expected `{`, found `)`
|
||||||
|
}
|
10
src/test/ui/issues/issue-61858.stderr
Normal file
10
src/test/ui/issues/issue-61858.stderr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
error: expected `{`, found `)`
|
||||||
|
--> $DIR/issue-61858.rs:2:15
|
||||||
|
|
|
||||||
|
LL | (if foobar)
|
||||||
|
| -- ^ expected `{`
|
||||||
|
| |
|
||||||
|
| this `if` statement has a condition, but no block
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
59
src/test/ui/rfc1445/allow-use-behind-cousin-variant.rs
Normal file
59
src/test/ui/rfc1445/allow-use-behind-cousin-variant.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// rust-lang/rust#62614: we want to allow matching on constants of types that
|
||||||
|
// have non-structural-match variants, *if* the constant itself does not use
|
||||||
|
// any such variant.
|
||||||
|
|
||||||
|
// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set
|
||||||
|
// to its default, so that we will not issue a diangostic even if
|
||||||
|
// rust-lang/rust#62614 remains an open issue.
|
||||||
|
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
struct Sum(u32, u32);
|
||||||
|
|
||||||
|
impl PartialEq for Sum {
|
||||||
|
fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Sum { }
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum Eek {
|
||||||
|
TheConst,
|
||||||
|
UnusedByTheConst(Sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
const THE_CONST: Eek = Eek::TheConst;
|
||||||
|
const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0));
|
||||||
|
|
||||||
|
const EEK_ZERO: &[Eek] = &[];
|
||||||
|
const EEK_ONE: &[Eek] = &[THE_CONST];
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
match Eek::UnusedByTheConst(Sum(1,2)) {
|
||||||
|
ref sum if sum == &SUM_THREE => { println!("Hello 0"); }
|
||||||
|
_ => { println!("Gbye"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
match Eek::TheConst {
|
||||||
|
THE_CONST => { println!("Hello 1"); }
|
||||||
|
_ => { println!("Gbye"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
match & &Eek::TheConst {
|
||||||
|
& & THE_CONST => { println!("Hello 2"); }
|
||||||
|
_ => { println!("Gbye"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
match & & &[][..] {
|
||||||
|
& & EEK_ZERO => { println!("Hello 3"); }
|
||||||
|
& & EEK_ONE => { println!("Gbye"); }
|
||||||
|
_ => { println!("Gbye"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
match & & &[Eek::TheConst][..] {
|
||||||
|
& & EEK_ZERO => { println!("Gby"); }
|
||||||
|
& & EEK_ONE => { println!("Hello 4"); }
|
||||||
|
_ => { println!("Gbye"); }
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
// through that we had intended to reject.
|
// through that we had intended to reject.
|
||||||
//
|
//
|
||||||
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
||||||
// This impl makes NoDerive irreflexive.
|
// This impl makes NoDerive irreflexive.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// through that we had intended to reject.
|
// through that we had intended to reject.
|
||||||
//
|
//
|
||||||
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
|
||||||
LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// through that we had intended to reject.
|
// through that we had intended to reject.
|
||||||
//
|
//
|
||||||
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
|
||||||
LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// through that we had intended to reject.
|
// through that we had intended to reject.
|
||||||
//
|
//
|
||||||
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
|
||||||
LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// through that we had intended to reject.
|
// through that we had intended to reject.
|
||||||
//
|
//
|
||||||
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
|
||||||
LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// Issue 62307 pointed out a case where the checking for
|
// Issue 62307 pointed out a case where the checking for
|
||||||
// `#[structural_match]` was too shallow.
|
// `#[structural_match]` was too shallow.
|
||||||
|
#![warn(indirect_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -4,7 +4,11 @@ warning: to use a constant of type `B` in a pattern, `B` must be annotated with
|
||||||
LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: #[warn(indirect_structural_match)] on by default
|
note: lint level defined here
|
||||||
|
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
||||||
|
|
|
||||||
|
LL | #![warn(indirect_structural_match)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,14 @@ fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
|
||||||
//~^ HELP elide the single-use lifetime
|
//~^ HELP elide the single-use lifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Single<'a> { x: &'a u32 }
|
||||||
|
struct Double<'a, 'b> { f: &'a &'b u32 }
|
||||||
|
|
||||||
|
fn center<'m>(_: Single<'m>) {} //~ ERROR `'m` only used once
|
||||||
|
//~^ HELP elide the single-use lifetime
|
||||||
|
fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f } //~ ERROR `'y` only used once
|
||||||
|
//~^ HELP elide the single-use lifetime
|
||||||
|
fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f } //~ ERROR `'x` only used once
|
||||||
|
//~^ HELP elide the single-use lifetime
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -16,5 +16,37 @@ help: elide the single-use lifetime
|
||||||
LL | fn a(x: &u32) {
|
LL | fn a(x: &u32) {
|
||||||
| -- --
|
| -- --
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: lifetime parameter `'m` only used once
|
||||||
|
--> $DIR/one-use-in-fn-argument.rs:15:11
|
||||||
|
|
|
||||||
|
LL | fn center<'m>(_: Single<'m>) {}
|
||||||
|
| ^^ -- ...is used only here
|
||||||
|
| |
|
||||||
|
| this lifetime...
|
||||||
|
help: elide the single-use lifetime
|
||||||
|
|
|
||||||
|
LL | fn center(_: Single<'_>) {}
|
||||||
|
| -- ^^
|
||||||
|
|
||||||
|
error: lifetime parameter `'y` only used once
|
||||||
|
--> $DIR/one-use-in-fn-argument.rs:17:13
|
||||||
|
|
|
||||||
|
LL | fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f }
|
||||||
|
| ^^ this lifetime... -- ...is used only here
|
||||||
|
help: elide the single-use lifetime
|
||||||
|
|
|
||||||
|
LL | fn left<'x>(foo: Double<'x, '_>) -> &'x u32 { foo.f }
|
||||||
|
| -- ^^
|
||||||
|
|
||||||
|
error: lifetime parameter `'x` only used once
|
||||||
|
--> $DIR/one-use-in-fn-argument.rs:19:10
|
||||||
|
|
|
||||||
|
LL | fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f }
|
||||||
|
| ^^ this lifetime... -- ...is used only here
|
||||||
|
help: elide the single-use lifetime
|
||||||
|
|
|
||||||
|
LL | fn right<'y>(foo: Double<'_, 'y>) -> &'y u32 { foo.f }
|
||||||
|
| -- ^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,8 @@ struct Foo<'a>(u32, &'a ScribbleOnDrop);
|
||||||
|
|
||||||
impl<'a> Drop for Foo<'a> {
|
impl<'a> Drop for Foo<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is unsound,
|
// Use of `may_dangle` is unsound, because destructor accesses borrowed data
|
||||||
// because destructor accesses borrowed data in `self.1`
|
// in `self.1` and we must force that to strictly outlive `self`.
|
||||||
// and we must force that to strictly outlive `self`.
|
|
||||||
println!("Dropping Foo({}, {:?})", self.0, self.1);
|
println!("Dropping Foo({}, {:?})", self.0, self.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `first_dropped` does not live long enough
|
error[E0597]: `first_dropped` does not live long enough
|
||||||
--> $DIR/issue28498-reject-lifetime-param.rs:33:19
|
--> $DIR/issue28498-reject-lifetime-param.rs:32:19
|
||||||
|
|
|
|
||||||
LL | foo1 = Foo(1, &first_dropped);
|
LL | foo1 = Foo(1, &first_dropped);
|
||||||
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
||||||
|
|
|
@ -16,8 +16,7 @@ struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
|
||||||
|
|
||||||
impl<T> Drop for Foo<T> {
|
impl<T> Drop for Foo<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is unsound,
|
// Use of `may_dangle` is unsound, because we pass `T` to the callback in `self.2`
|
||||||
// because we pass `T` to the callback in `self.2`
|
|
||||||
// below, and thus potentially read from borrowed data.
|
// below, and thus potentially read from borrowed data.
|
||||||
println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
|
println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `first_dropped` does not live long enough
|
error[E0597]: `first_dropped` does not live long enough
|
||||||
--> $DIR/issue28498-reject-passed-to-fn.rs:35:19
|
--> $DIR/issue28498-reject-passed-to-fn.rs:34:19
|
||||||
|
|
|
|
||||||
LL | foo1 = Foo(1, &first_dropped, Box::new(callback));
|
LL | foo1 = Foo(1, &first_dropped, Box::new(callback));
|
||||||
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
||||||
|
|
|
@ -14,13 +14,12 @@ impl Drop for ScribbleOnDrop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo<T:fmt::Debug>(u32, T);
|
struct Foo<T: fmt::Debug>(u32, T);
|
||||||
|
|
||||||
impl<T:fmt::Debug> Drop for Foo<T> {
|
impl<T: fmt::Debug> Drop for Foo<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Use of `unsafe_destructor_blind_to_params` is unsound,
|
// Use of `may_dangle` is unsound, because we access `T` fmt method when we pass
|
||||||
// because we access `T` fmt method when we pass `self.1`
|
// `self.1` below, and thus potentially read from borrowed data.
|
||||||
// below, and thus potentially read from borrowed data.
|
|
||||||
println!("Dropping Foo({}, {:?})", self.0, self.1);
|
println!("Dropping Foo({}, {:?})", self.0, self.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `first_dropped` does not live long enough
|
error[E0597]: `first_dropped` does not live long enough
|
||||||
--> $DIR/issue28498-reject-trait-bound.rs:35:19
|
--> $DIR/issue28498-reject-trait-bound.rs:34:19
|
||||||
|
|
|
|
||||||
LL | foo1 = Foo(1, &first_dropped);
|
LL | foo1 = Foo(1, &first_dropped);
|
||||||
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
|
||||||
|
|
Loading…
Reference in a new issue