Auto merge of #83674 - Dylan-DPC:rollup-bcuc1hl, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #83568 (update comment at MaybeUninit::uninit_array) - #83571 (Constantify some slice methods) - #83579 (Improve pointer arithmetic docs) - #83645 (Wrap non-pre code blocks) - #83656 (Add a regression test for issue-82865) - #83662 (Update books) - #83667 (Suggest box/pin/arc ing receiver on method calls) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
16156fb278
@ -6,7 +6,7 @@
|
||||
use crate::check::cast;
|
||||
use crate::check::coercion::CoerceMany;
|
||||
use crate::check::fatally_break_rust;
|
||||
use crate::check::method::{probe, MethodError, SelfSource};
|
||||
use crate::check::method::SelfSource;
|
||||
use crate::check::report_unexpected_variant_res;
|
||||
use crate::check::BreakableCtxt;
|
||||
use crate::check::Diverges;
|
||||
@ -30,7 +30,6 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, QPath};
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
@ -461,7 +460,11 @@ fn check_lang_item_path(
|
||||
self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
|
||||
}
|
||||
|
||||
fn check_expr_path(&self, qpath: &hir::QPath<'_>, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
|
||||
fn check_expr_path(
|
||||
&self,
|
||||
qpath: &'tcx hir::QPath<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id, expr.span);
|
||||
let ty = match res {
|
||||
@ -947,7 +950,16 @@ fn check_method_call(
|
||||
}
|
||||
Err(error) => {
|
||||
if segment.ident.name != kw::Empty {
|
||||
self.report_extended_method_error(segment, span, args, rcvr_t, error);
|
||||
if let Some(mut err) = self.report_method_error(
|
||||
span,
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
SelfSource::MethodCall(&args[0]),
|
||||
error,
|
||||
Some(args),
|
||||
) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
@ -964,59 +976,6 @@ fn check_method_call(
|
||||
)
|
||||
}
|
||||
|
||||
fn report_extended_method_error(
|
||||
&self,
|
||||
segment: &hir::PathSegment<'_>,
|
||||
span: Span,
|
||||
args: &'tcx [hir::Expr<'tcx>],
|
||||
rcvr_t: Ty<'tcx>,
|
||||
error: MethodError<'tcx>,
|
||||
) {
|
||||
let rcvr = &args[0];
|
||||
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
|
||||
if let Some(new_rcvr_t) = new_rcvr_t {
|
||||
if let Ok(pick) = self.lookup_probe(
|
||||
span,
|
||||
segment.ident,
|
||||
new_rcvr_t,
|
||||
rcvr,
|
||||
probe::ProbeScope::AllTraits,
|
||||
) {
|
||||
debug!("try_alt_rcvr: pick candidate {:?}", pick);
|
||||
// Make sure the method is defined for the *actual* receiver:
|
||||
// we don't want to treat `Box<Self>` as a receiver if
|
||||
// it only works because of an autoderef to `&self`
|
||||
if pick.autoderefs == 0 {
|
||||
err.span_label(
|
||||
pick.item.ident.span,
|
||||
&format!("the method is available for `{}` here", new_rcvr_t),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(mut err) = self.report_method_error(
|
||||
span,
|
||||
rcvr_t,
|
||||
segment.ident,
|
||||
SelfSource::MethodCall(rcvr),
|
||||
error,
|
||||
Some(args),
|
||||
) {
|
||||
if let ty::Adt(..) = rcvr_t.kind() {
|
||||
// Try alternative arbitrary self types that could fulfill this call.
|
||||
// FIXME: probe for all types that *could* be arbitrary self-types, not
|
||||
// just this list.
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
|
||||
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_cast(
|
||||
&self,
|
||||
e: &'tcx hir::Expr<'tcx>,
|
||||
|
@ -905,12 +905,12 @@ pub(in super::super) fn resolve_lang_item_path(
|
||||
|
||||
/// Resolves an associated value path into a base type and associated constant, or method
|
||||
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
|
||||
pub fn resolve_ty_and_res_ufcs<'b>(
|
||||
pub fn resolve_ty_and_res_ufcs(
|
||||
&self,
|
||||
qpath: &'b QPath<'b>,
|
||||
qpath: &'tcx QPath<'tcx>,
|
||||
hir_id: hir::HirId,
|
||||
span: Span,
|
||||
) -> (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]) {
|
||||
) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
|
||||
debug!("resolve_ty_and_res_ufcs: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span);
|
||||
let (ty, qself, item_segment) = match *qpath {
|
||||
QPath::Resolved(ref opt_qself, ref path) => {
|
||||
|
@ -45,6 +45,7 @@ pub struct MethodCallee<'tcx> {
|
||||
pub sig: ty::FnSig<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MethodError<'tcx> {
|
||||
// Did not find an applicable method, but we did find various near-misses that may work.
|
||||
NoMatch(NoMatchData<'tcx>),
|
||||
@ -66,6 +67,7 @@ pub enum MethodError<'tcx> {
|
||||
|
||||
// Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
|
||||
// could lead to matches if satisfied, and a list of not-in-scope traits which may work.
|
||||
#[derive(Debug)]
|
||||
pub struct NoMatchData<'tcx> {
|
||||
pub static_candidates: Vec<CandidateSource>,
|
||||
pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
|
||||
|
@ -68,12 +68,12 @@ fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_method_error<'b>(
|
||||
pub fn report_method_error(
|
||||
&self,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: Ident,
|
||||
source: SelfSource<'b>,
|
||||
source: SelfSource<'tcx>,
|
||||
error: MethodError<'tcx>,
|
||||
args: Option<&'tcx [hir::Expr<'tcx>]>,
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
@ -323,8 +323,8 @@ pub fn report_method_error<'b>(
|
||||
err.span_suggestion(
|
||||
lit.span,
|
||||
&format!(
|
||||
"you must specify a concrete type for \
|
||||
this numeric value, like `{}`",
|
||||
"you must specify a concrete type for this numeric value, \
|
||||
like `{}`",
|
||||
concrete_type
|
||||
),
|
||||
format!("{}_{}", snippet, concrete_type),
|
||||
@ -975,17 +975,78 @@ fn suggest_valid_traits(
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_traits_to_import<'b>(
|
||||
fn suggest_traits_to_import(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
item_name: Ident,
|
||||
source: SelfSource<'b>,
|
||||
source: SelfSource<'tcx>,
|
||||
valid_out_of_scope_traits: Vec<DefId>,
|
||||
unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
|
||||
) {
|
||||
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
|
||||
let mut alt_rcvr_sugg = false;
|
||||
if let SelfSource::MethodCall(rcvr) = source {
|
||||
info!(?span, ?item_name, ?rcvr_ty, ?rcvr);
|
||||
if let ty::Adt(..) = rcvr_ty.kind() {
|
||||
// Try alternative arbitrary self types that could fulfill this call.
|
||||
// FIXME: probe for all types that *could* be arbitrary self-types, not
|
||||
// just this list.
|
||||
for (rcvr_ty, post) in &[
|
||||
(rcvr_ty, ""),
|
||||
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
|
||||
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
|
||||
] {
|
||||
for (rcvr_ty, pre) in &[
|
||||
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
|
||||
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
|
||||
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
|
||||
(self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
|
||||
] {
|
||||
if let Some(new_rcvr_t) = *rcvr_ty {
|
||||
if let Ok(pick) = self.lookup_probe(
|
||||
span,
|
||||
item_name,
|
||||
new_rcvr_t,
|
||||
rcvr,
|
||||
crate::check::method::probe::ProbeScope::AllTraits,
|
||||
) {
|
||||
debug!("try_alt_rcvr: pick candidate {:?}", pick);
|
||||
// Make sure the method is defined for the *actual* receiver:
|
||||
// we don't want to treat `Box<Self>` as a receiver if
|
||||
// it only works because of an autoderef to `&self`
|
||||
if pick.autoderefs == 0
|
||||
// We don't want to suggest a container type when the missing method is
|
||||
// `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
|
||||
// far from what the user really wants.
|
||||
&& Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
|
||||
{
|
||||
err.span_label(
|
||||
pick.item.ident.span,
|
||||
&format!(
|
||||
"the method is available for `{}` here",
|
||||
new_rcvr_t
|
||||
),
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
"consider wrapping the receiver expression with the \
|
||||
appropriate type",
|
||||
vec![
|
||||
(rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
|
||||
(rcvr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
// We don't care about the other suggestions.
|
||||
alt_rcvr_sugg = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1075,6 +1136,9 @@ fn suggest_traits_to_import<'b>(
|
||||
"the method might not be found because of this arbitrary self type",
|
||||
);
|
||||
}
|
||||
if alt_rcvr_sugg {
|
||||
return;
|
||||
}
|
||||
|
||||
if !candidates.is_empty() {
|
||||
// Sort from most relevant to least relevant.
|
||||
@ -1284,7 +1348,12 @@ fn suggest_traits_to_import<'b>(
|
||||
|
||||
/// Checks whether there is a local type somewhere in the chain of
|
||||
/// autoderefs of `rcvr_ty`.
|
||||
fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool {
|
||||
fn type_derefs_to_local(
|
||||
&self,
|
||||
span: Span,
|
||||
rcvr_ty: Ty<'tcx>,
|
||||
source: SelfSource<'tcx>,
|
||||
) -> bool {
|
||||
fn is_local(ty: Ty<'_>) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Adt(def, _) => def.did.is_local(),
|
||||
@ -1310,7 +1379,7 @@ fn is_local(ty: Ty<'_>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum SelfSource<'a> {
|
||||
QPath(&'a hir::Ty<'a>),
|
||||
MethodCall(&'a hir::Expr<'a> /* rcvr */),
|
||||
|
@ -861,7 +861,7 @@ fn emit_bad_pat_path(
|
||||
fn check_pat_tuple_struct(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
qpath: &hir::QPath<'_>,
|
||||
qpath: &'tcx hir::QPath<'tcx>,
|
||||
subpats: &'tcx [&'tcx Pat<'tcx>],
|
||||
ddpos: Option<usize>,
|
||||
expected: Ty<'tcx>,
|
||||
|
@ -319,9 +319,9 @@ pub const fn uninit() -> MaybeUninit<T> {
|
||||
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
|
||||
///
|
||||
/// Note: in a future Rust version this method may become unnecessary
|
||||
/// when array literal syntax allows
|
||||
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
|
||||
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
|
||||
/// when Rust allows
|
||||
/// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
|
||||
/// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -184,8 +184,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@ -210,6 +209,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_offset`]: #method.wrapping_offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -245,9 +245,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -265,10 +264,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
|
||||
/// words, leaving the allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`offset`]: #method.offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -314,8 +311,7 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and other pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * Both pointers must be *derived from* a pointer to the same object.
|
||||
/// (See below for an example.)
|
||||
@ -345,6 +341,7 @@ pub const fn wrapping_offset(self, count: isize) -> *const T
|
||||
/// such large allocations either.)
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -468,8 +465,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@ -494,6 +490,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_add`]: #method.wrapping_add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -532,8 +529,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
|
||||
///
|
||||
@ -558,6 +554,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_sub`]: #method.wrapping_sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -594,9 +591,8 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -614,10 +610,8 @@ pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -659,9 +653,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -679,10 +672,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`sub`]: #method.sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -997,7 +988,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
|
||||
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
|
||||
/// and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@ -1019,6 +1010,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
|
||||
/// See also [`slice::from_raw_parts`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
|
@ -55,6 +55,14 @@
|
||||
//! has size 0, i.e., even if memory is not actually touched. Consider using
|
||||
//! [`NonNull::dangling`] in such cases.
|
||||
//!
|
||||
//! ## Allocated object
|
||||
//!
|
||||
//! For several operations, such as [`offset`] or field projections (`expr.field`), the notion of an
|
||||
//! "allocated object" becomes relevant. An allocated object is a contiguous region of memory.
|
||||
//! Common examples of allocated objects include stack-allocated variables (each variable is a
|
||||
//! separate allocated object), heap allocations (each allocation created by the global allocator is
|
||||
//! a separate allocated object), and `static` variables.
|
||||
//!
|
||||
//! [aliasing]: ../../nomicon/aliasing.html
|
||||
//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
|
||||
//! [ub]: ../../reference/behavior-considered-undefined.html
|
||||
|
@ -189,8 +189,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@ -215,6 +214,7 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_offset`]: #method.wrapping_offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -251,9 +251,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -271,10 +270,8 @@ pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
|
||||
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
|
||||
/// words, leaving the allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`offset`]: #method.offset
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -485,8 +482,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and other pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * Both pointers must be *derived from* a pointer to the same object.
|
||||
/// (See below for an example.)
|
||||
@ -516,6 +512,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// such large allocations either.)
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -575,8 +572,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
|
||||
///
|
||||
@ -639,8 +635,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// Behavior:
|
||||
///
|
||||
/// * Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of the same allocated object. Note that in Rust,
|
||||
/// every (stack-allocated) variable is considered a separate allocated object.
|
||||
/// byte past the end of the same [allocated object].
|
||||
///
|
||||
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
|
||||
///
|
||||
@ -665,6 +660,7 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// enables more aggressive compiler optimizations.
|
||||
///
|
||||
/// [`wrapping_sub`]: #method.wrapping_sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -701,9 +697,8 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -721,10 +716,8 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`add`]: #method.add
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -766,9 +759,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
///
|
||||
/// This operation itself is always safe, but using the resulting pointer is not.
|
||||
///
|
||||
/// The resulting pointer remains attached to the same allocated object that `self` points to.
|
||||
/// It may *not* be used to access a different allocated object. Note that in Rust, every
|
||||
/// (stack-allocated) variable is considered a separate allocated object.
|
||||
/// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
|
||||
/// be used to read or write other allocated objects.
|
||||
///
|
||||
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
|
||||
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
|
||||
@ -786,10 +778,8 @@ pub const fn wrapping_add(self, count: usize) -> Self
|
||||
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
|
||||
/// allocated object and then re-entering it later is permitted.
|
||||
///
|
||||
/// If you need to cross object boundaries, cast the pointer to an integer and
|
||||
/// do the arithmetic there.
|
||||
///
|
||||
/// [`sub`]: #method.sub
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1261,7 +1251,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
|
||||
/// and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@ -1283,6 +1273,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
|
||||
/// See also [`slice::from_raw_parts`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
@ -1311,7 +1302,7 @@ pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
/// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
|
||||
/// many bytes, and it must be properly aligned. This means in particular:
|
||||
///
|
||||
/// * The entire memory range of this slice must be contained within a single allocated object!
|
||||
/// * The entire memory range of this slice must be contained within a single [allocated object]!
|
||||
/// Slices can never span across multiple allocated objects.
|
||||
///
|
||||
/// * The pointer must be aligned even for zero-length slices. One
|
||||
@ -1333,6 +1324,7 @@ pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
|
||||
/// See also [`slice::from_raw_parts_mut`][].
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [allocated object]: crate::ptr#allocated-object
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
|
||||
pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
|
||||
|
@ -148,8 +148,9 @@ pub const fn is_empty(&self) -> bool {
|
||||
/// assert_eq!(None, w.first());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn first(&self) -> Option<&T> {
|
||||
pub const fn first(&self) -> Option<&T> {
|
||||
if let [first, ..] = self { Some(first) } else { None }
|
||||
}
|
||||
|
||||
@ -166,8 +167,9 @@ pub fn first(&self) -> Option<&T> {
|
||||
/// assert_eq!(x, &[5, 1, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn first_mut(&mut self) -> Option<&mut T> {
|
||||
pub const fn first_mut(&mut self) -> Option<&mut T> {
|
||||
if let [first, ..] = self { Some(first) } else { None }
|
||||
}
|
||||
|
||||
@ -184,8 +186,9 @@ pub fn first_mut(&mut self) -> Option<&mut T> {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
pub const fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
|
||||
}
|
||||
|
||||
@ -204,8 +207,9 @@ pub fn split_first(&self) -> Option<(&T, &[T])> {
|
||||
/// assert_eq!(x, &[3, 4, 5]);
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
|
||||
}
|
||||
|
||||
@ -222,8 +226,9 @@ pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
pub const fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
if let [init @ .., last] = self { Some((last, init)) } else { None }
|
||||
}
|
||||
|
||||
@ -242,8 +247,9 @@ pub fn split_last(&self) -> Option<(&T, &[T])> {
|
||||
/// assert_eq!(x, &[4, 5, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "slice_splits", since = "1.5.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
if let [init @ .., last] = self { Some((last, init)) } else { None }
|
||||
}
|
||||
|
||||
@ -259,8 +265,9 @@ pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
|
||||
/// assert_eq!(None, w.last());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn last(&self) -> Option<&T> {
|
||||
pub const fn last(&self) -> Option<&T> {
|
||||
if let [.., last] = self { Some(last) } else { None }
|
||||
}
|
||||
|
||||
@ -277,8 +284,9 @@ pub fn last(&self) -> Option<&T> {
|
||||
/// assert_eq!(x, &[0, 1, 10]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
|
||||
#[inline]
|
||||
pub fn last_mut(&mut self) -> Option<&mut T> {
|
||||
pub const fn last_mut(&mut self) -> Option<&mut T> {
|
||||
if let [.., last] = self { Some(last) } else { None }
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit fc2f690fc16592abbead2360cfc0a42f5df78052
|
||||
Subproject commit b54090a99ec7c4b46a5203a9c927fdbc311bb1f5
|
@ -1 +1 @@
|
||||
Subproject commit f61685755fad7d3b88b4645adfbf461d500563a2
|
||||
Subproject commit d3f2ace94d51610cf3e3c265705bb8416d37f8e4
|
@ -1 +1 @@
|
||||
Subproject commit d10a0af8dca25d9d548ca6a369fd66ad06acb3c9
|
||||
Subproject commit fd97729e2d82f8b08d68a31c9bfdf0c37a7fd542
|
@ -1 +1 @@
|
||||
Subproject commit eead22c6c030fa4f3a167d1798658c341199e2ae
|
||||
Subproject commit 29d91f591c90dd18fdca6d23f1a9caf9c139d0d7
|
@ -1 +1 @@
|
||||
Subproject commit 67ebd4b55dba44edfc351621cef6e5e758169c55
|
||||
Subproject commit 0687daac28939c476df51778f5a1d1aff1a3fddf
|
@ -424,7 +424,9 @@ nav.sub {
|
||||
text-overflow: ellipsis;
|
||||
margin: 0;
|
||||
}
|
||||
.docblock-short code {
|
||||
/* Wrap non-pre code blocks (`text`) but not (```text```). */
|
||||
.docblock > :not(pre) > code,
|
||||
.docblock-short > :not(pre) > code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
|
47
src/test/ui/async-await/pin-needed-to-poll.rs
Normal file
47
src/test/ui/async-await/pin-needed-to-poll.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
struct Sleep;
|
||||
|
||||
impl Future for Sleep {
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Sleep {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn sleep() -> Sleep {
|
||||
Sleep
|
||||
}
|
||||
|
||||
|
||||
struct MyFuture {
|
||||
sleep: Sleep,
|
||||
}
|
||||
|
||||
impl MyFuture {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
sleep: sleep(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for MyFuture {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.sleep.poll(cx)
|
||||
//~^ ERROR no method named `poll` found for struct `Sleep` in the current scope
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
22
src/test/ui/async-await/pin-needed-to-poll.stderr
Normal file
22
src/test/ui/async-await/pin-needed-to-poll.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error[E0599]: no method named `poll` found for struct `Sleep` in the current scope
|
||||
--> $DIR/pin-needed-to-poll.rs:42:20
|
||||
|
|
||||
LL | struct Sleep;
|
||||
| ------------- method `poll` not found for this
|
||||
...
|
||||
LL | self.sleep.poll(cx)
|
||||
| ^^^^ method not found in `Sleep`
|
||||
|
|
||||
::: $SRC_DIR/core/src/future/future.rs:LL:COL
|
||||
|
|
||||
LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
|
||||
| ---- the method is available for `Pin<&mut Sleep>` here
|
||||
|
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Pin::new(&mut self.sleep).poll(cx)
|
||||
| ^^^^^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -6,14 +6,6 @@ LL | struct Foo {
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Foo>` here
|
||||
| the method is available for `Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -12,14 +12,6 @@ LL | struct NotClone;
|
||||
...
|
||||
LL | Bar::<NotClone> { x: 1 }.clone();
|
||||
| ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Bar<NotClone>>` here
|
||||
| the method is available for `Rc<Bar<NotClone>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`NotClone: Clone`
|
||||
|
@ -6,14 +6,6 @@ LL | struct C {
|
||||
...
|
||||
LL | let _d = c.clone();
|
||||
| ^^^^^ method not found in `C`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<C>` here
|
||||
| the method is available for `Rc<C>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
@ -8,14 +8,6 @@ LL | let _ = Struct::<A>::new().clone();
|
||||
|
|
||||
LL | pub struct Struct<A>(A);
|
||||
| ------------------------ doesn't satisfy `Struct<A>: Clone`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Struct<A>>` here
|
||||
| the method is available for `Rc<Struct<A>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`A: Clone`
|
||||
|
@ -3,14 +3,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco
|
||||
|
|
||||
LL | let _z = (*y).clone();
|
||||
| ^^^^^ method not found in `c_void`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<c_void>` here
|
||||
| the method is available for `Rc<c_void>` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,14 +6,6 @@ LL | struct Foo {
|
||||
...
|
||||
LL | let _y = x.clone();
|
||||
| ^^^^^ method not found in `Foo`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Foo>` here
|
||||
| the method is available for `Rc<Foo>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following trait defines an item `clone`, perhaps you need to implement it:
|
||||
|
13
src/test/ui/resolve/issue-82865.rs
Normal file
13
src/test/ui/resolve/issue-82865.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Regression test for #82865.
|
||||
|
||||
#![feature(decl_macro)]
|
||||
|
||||
use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`?
|
||||
|
||||
macro mac () {
|
||||
Box::z //~ ERROR: no function or associated item
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mac!();
|
||||
}
|
21
src/test/ui/resolve/issue-82865.stderr
Normal file
21
src/test/ui/resolve/issue-82865.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0433]: failed to resolve: maybe a missing crate `x`?
|
||||
--> $DIR/issue-82865.rs:5:5
|
||||
|
|
||||
LL | use x::y::z;
|
||||
| ^ maybe a missing crate `x`?
|
||||
|
||||
error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope
|
||||
--> $DIR/issue-82865.rs:8:10
|
||||
|
|
||||
LL | Box::z
|
||||
| ^ function or associated item not found in `Box<_, _>`
|
||||
...
|
||||
LL | mac!();
|
||||
| ------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0433, E0599.
|
||||
For more information about an error, try `rustc --explain E0433`.
|
@ -9,6 +9,11 @@ LL | fn foo(self: Box<Self>) {}
|
||||
...
|
||||
LL | A.foo();
|
||||
| ^^^ method not found in `A`
|
||||
|
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Box::new(A).foo();
|
||||
| ^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | struct A;
|
||||
...
|
||||
LL | A.foo()
|
||||
| ^^^ method not found in `A`
|
||||
|
|
||||
help: consider wrapping the receiver expression with the appropriate type
|
||||
|
|
||||
LL | Box::new(A).foo()
|
||||
| ^^^^^^^^^ ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:36:11
|
||||
|
|
||||
LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
||||
| - ^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'a` here: `'a,`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
@ -6,14 +6,6 @@ LL | struct Qux;
|
||||
...
|
||||
LL | Qux.clone();
|
||||
| ^^^^^ method not found in `Qux`
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Qux>` here
|
||||
| the method is available for `Rc<Qux>` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
|
||||
|
@ -25,14 +25,6 @@ LL | struct CloneNoCopy;
|
||||
...
|
||||
LL | let w = u.clone();
|
||||
| ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<U5<CloneNoCopy>>` here
|
||||
| the method is available for `Rc<U5<CloneNoCopy>>` here
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`CloneNoCopy: Copy`
|
||||
|
@ -10,14 +10,6 @@ LL | trait Foo {
|
||||
LL | let _z = y.clone();
|
||||
| ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Box<dyn Foo>>` here
|
||||
| the method is available for `Rc<Box<dyn Foo>>` here
|
||||
|
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
LL | / pub struct Box<
|
||||
|
@ -7,14 +7,6 @@ LL | struct R {
|
||||
LL | let _j = i.clone();
|
||||
| ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
|
||||
|
|
||||
::: $SRC_DIR/core/src/clone.rs:LL:COL
|
||||
|
|
||||
LL | fn clone(&self) -> Self;
|
||||
| -----
|
||||
| |
|
||||
| the method is available for `Arc<Box<R>>` here
|
||||
| the method is available for `Rc<Box<R>>` here
|
||||
|
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
LL | / pub struct Box<
|
||||
|
Loading…
Reference in New Issue
Block a user