Rollup merge of #139751 - frank-king:feature/pin-project, r=Nadrieril,traviscross
Implement pin-project in pattern matching for `&pin mut|const T` This PR implements part of rust-lang/rust#130494. It supports pin-project in pattern matching for `&pin mut|const T`. ~Pin-projection by field access (i.e. `&pin mut|const place.field`) is not fully supported yet since pinned-borrow is not ready (rust-lang/rust#135731).~ CC ``````@traviscross``````
This commit is contained in:
commit
dc9060688a
60 changed files with 2437 additions and 118 deletions
|
|
@ -789,14 +789,14 @@ pub struct PatField {
|
|||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
pub enum ByRef {
|
||||
Yes(Mutability),
|
||||
Yes(Pinnedness, Mutability),
|
||||
No,
|
||||
}
|
||||
|
||||
impl ByRef {
|
||||
#[must_use]
|
||||
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
|
||||
if let ByRef::Yes(old_mutbl) = &mut self {
|
||||
if let ByRef::Yes(_, old_mutbl) = &mut self {
|
||||
*old_mutbl = cmp::min(*old_mutbl, mutbl);
|
||||
}
|
||||
self
|
||||
|
|
@ -814,20 +814,33 @@ pub struct BindingMode(pub ByRef, pub Mutability);
|
|||
|
||||
impl BindingMode {
|
||||
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
|
||||
pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not);
|
||||
pub const REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Not);
|
||||
pub const REF_PIN: Self =
|
||||
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Not);
|
||||
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
|
||||
pub const REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Not);
|
||||
pub const MUT_REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Mut);
|
||||
pub const MUT_REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Mut);
|
||||
pub const REF_MUT: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Not);
|
||||
pub const REF_PIN_MUT: Self =
|
||||
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Not);
|
||||
pub const MUT_REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Mut);
|
||||
pub const MUT_REF_PIN: Self =
|
||||
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Mut);
|
||||
pub const MUT_REF_MUT: Self =
|
||||
Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Mut);
|
||||
pub const MUT_REF_PIN_MUT: Self =
|
||||
Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Mut);
|
||||
|
||||
pub fn prefix_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::NONE => "",
|
||||
Self::REF => "ref ",
|
||||
Self::REF_PIN => "ref pin const ",
|
||||
Self::MUT => "mut ",
|
||||
Self::REF_MUT => "ref mut ",
|
||||
Self::REF_PIN_MUT => "ref pin mut ",
|
||||
Self::MUT_REF => "mut ref ",
|
||||
Self::MUT_REF_PIN => "mut ref pin ",
|
||||
Self::MUT_REF_MUT => "mut ref mut ",
|
||||
Self::MUT_REF_PIN_MUT => "mut ref pin mut ",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
crate::tokenstream::TokenStream,
|
||||
Movability,
|
||||
Mutability,
|
||||
Pinnedness,
|
||||
Result<(), rustc_span::ErrorGuaranteed>,
|
||||
rustc_data_structures::fx::FxHashMap<Symbol, usize>,
|
||||
rustc_span::ErrorGuaranteed,
|
||||
|
|
|
|||
|
|
@ -311,3 +311,10 @@ pub enum Pinnedness {
|
|||
Not,
|
||||
Pinned,
|
||||
}
|
||||
|
||||
impl Pinnedness {
|
||||
/// Return `true` if self is pinned
|
||||
pub fn is_pinned(self) -> bool {
|
||||
matches!(self, Self::Pinned)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1712,10 +1712,15 @@ impl<'a> State<'a> {
|
|||
if mutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
if let ByRef::Yes(rmutbl) = by_ref {
|
||||
if let ByRef::Yes(pinnedness, rmutbl) = by_ref {
|
||||
self.word_nbsp("ref");
|
||||
if pinnedness.is_pinned() {
|
||||
self.word_nbsp("pin");
|
||||
}
|
||||
if rmutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
} else if pinnedness.is_pinned() {
|
||||
self.word_nbsp("const");
|
||||
}
|
||||
}
|
||||
self.print_ident(*ident);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ pub(crate) mod must_use;
|
|||
pub(crate) mod no_implicit_prelude;
|
||||
pub(crate) mod non_exhaustive;
|
||||
pub(crate) mod path;
|
||||
pub(crate) mod pin_v2;
|
||||
pub(crate) mod proc_macro_attrs;
|
||||
pub(crate) mod prototype;
|
||||
pub(crate) mod repr;
|
||||
|
|
|
|||
21
compiler/rustc_attr_parsing/src/attributes/pin_v2.rs
Normal file
21
compiler/rustc_attr_parsing/src/attributes/pin_v2.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use rustc_hir::Target;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
|
||||
use crate::context::Stage;
|
||||
use crate::target_checking::AllowedTargets;
|
||||
use crate::target_checking::Policy::Allow;
|
||||
|
||||
pub(crate) struct PinV2Parser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PinV2Parser {
|
||||
const PATH: &[Symbol] = &[sym::pin_v2];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Union),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PinV2;
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@ use crate::attributes::must_use::MustUseParser;
|
|||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
use crate::attributes::non_exhaustive::NonExhaustiveParser;
|
||||
use crate::attributes::path::PathParser as PathAttributeParser;
|
||||
use crate::attributes::pin_v2::PinV2Parser;
|
||||
use crate::attributes::proc_macro_attrs::{
|
||||
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
|
||||
};
|
||||
|
|
@ -233,6 +234,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PinV2Parser>>,
|
||||
Single<WithoutArgs<PointeeParser>>,
|
||||
Single<WithoutArgs<ProcMacroAttributeParser>>,
|
||||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
|
|
|
|||
|
|
@ -1188,7 +1188,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: BindingMode(ByRef::Yes(_), _),
|
||||
binding_mode: BindingMode(ByRef::Yes(..), _),
|
||||
..
|
||||
})) => {
|
||||
let pattern_span: Span = local_decl.source_info.span;
|
||||
|
|
|
|||
|
|
@ -2582,6 +2582,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
_ => bug!("Deref of unexpected type: {:?}", base_ty),
|
||||
}
|
||||
}
|
||||
// Check as the inner reference type if it is a field projection
|
||||
// from the `&pin` pattern
|
||||
ProjectionElem::Field(FieldIdx::ZERO, _)
|
||||
if let Some(adt) =
|
||||
place_base.ty(self.body(), self.infcx.tcx).ty.ty_adt_def()
|
||||
&& adt.is_pin()
|
||||
&& self.infcx.tcx.features().pin_ergonomics() =>
|
||||
{
|
||||
self.is_mutable(place_base, is_local_mutation_allowed)
|
||||
}
|
||||
// All other projections are owned by their base path, so mutable if
|
||||
// base path is mutable
|
||||
ProjectionElem::Field(..)
|
||||
|
|
|
|||
|
|
@ -893,6 +893,15 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::No, loop_match, experimental!(loop_match)
|
||||
),
|
||||
|
||||
// The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment
|
||||
// that allows structurally pinning, tracked in:
|
||||
//
|
||||
// - https://github.com/rust-lang/rust/issues/130494
|
||||
gated!(
|
||||
pin_v2, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes, pin_ergonomics, experimental!(pin_v2),
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes: Stability, deprecation, and unsafe:
|
||||
// ==========================================================================
|
||||
|
|
|
|||
|
|
@ -637,6 +637,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[pattern_complexity_limit]`
|
||||
PatternComplexityLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
||||
|
||||
/// Represents `#[pin_v2]`
|
||||
PinV2(Span),
|
||||
|
||||
/// Represents `#[pointee]`
|
||||
Pointee(Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ impl AttributeKind {
|
|||
PassByValue(..) => Yes,
|
||||
Path(..) => No,
|
||||
PatternComplexityLimit { .. } => No,
|
||||
PinV2(..) => Yes,
|
||||
Pointee(..) => No,
|
||||
ProcMacro(..) => No,
|
||||
ProcMacroAttribute(..) => No,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_ast::{
|
|||
pub use rustc_ast::{
|
||||
AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
|
||||
BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
|
||||
MetaItemInner, MetaItemLit, Movability, Mutability, UnOp,
|
||||
MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, UnOp,
|
||||
};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ fn resolve_local<'tcx>(
|
|||
// & expression, and its lifetime would be extended to the end of the block (due
|
||||
// to a different rule, not the below code).
|
||||
match pat.kind {
|
||||
PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(_), _), ..) => true,
|
||||
PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(..), _), ..) => true,
|
||||
|
||||
PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)),
|
||||
|
||||
|
|
|
|||
|
|
@ -1925,10 +1925,15 @@ impl<'a> State<'a> {
|
|||
if mutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
if let ByRef::Yes(rmutbl) = by_ref {
|
||||
if let ByRef::Yes(pinnedness, rmutbl) = by_ref {
|
||||
self.word_nbsp("ref");
|
||||
if pinnedness.is_pinned() {
|
||||
self.word_nbsp("pin");
|
||||
}
|
||||
if rmutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
} else if pinnedness.is_pinned() {
|
||||
self.word_nbsp("const");
|
||||
}
|
||||
}
|
||||
self.print_ident(ident);
|
||||
|
|
|
|||
|
|
@ -227,6 +227,10 @@ hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function
|
|||
.suggestion = cast the value to `{$cast_ty}`
|
||||
.teach_help = certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's numeric promotion rules
|
||||
|
||||
hir_typeck_project_on_non_pin_project_type = cannot project on type that is not `#[pin_v2]`
|
||||
.note = type defined here
|
||||
.suggestion = add `#[pin_v2]` here
|
||||
|
||||
hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len ->
|
||||
[1] auto trait {$traits}
|
||||
*[other] auto traits {$traits}
|
||||
|
|
|
|||
|
|
@ -1156,3 +1156,14 @@ pub(crate) struct ConstContinueBadLabel {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_project_on_non_pin_project_type)]
|
||||
pub(crate) struct ProjectOnNonPinProjectType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[note]
|
||||
pub def_span: Option<Span>,
|
||||
#[suggestion(code = "#[pin_v2]\n", applicability = "machine-applicable")]
|
||||
pub sugg_span: Option<Span>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -986,7 +986,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
// of the pattern, as this just looks confusing, instead use the span
|
||||
// of the discriminant.
|
||||
match bm.0 {
|
||||
hir::ByRef::Yes(m) => {
|
||||
hir::ByRef::Yes(_, m) => {
|
||||
let bk = ty::BorrowKind::from_mutbl(m);
|
||||
self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
|
||||
}
|
||||
|
|
@ -1004,7 +1004,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
// Deref patterns on boxes don't borrow, so we ignore them here.
|
||||
// HACK: this could be a fake pattern corresponding to a deref inserted by match
|
||||
// ergonomics, in which case `pat.hir_id` will be the id of the subpattern.
|
||||
if let hir::ByRef::Yes(mutability) =
|
||||
if let hir::ByRef::Yes(_, mutability) =
|
||||
self.cx.typeck_results().deref_pat_borrow_mode(place.place.ty(), subpattern)
|
||||
{
|
||||
let bk = ty::BorrowKind::from_mutbl(mutability);
|
||||
|
|
@ -1256,7 +1256,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
.get(pat.hir_id)
|
||||
.expect("missing binding mode");
|
||||
|
||||
if matches!(bm.0, hir::ByRef::Yes(_)) {
|
||||
if let hir::ByRef::Yes(pinnedness, _) = bm.0 {
|
||||
let base_ty = if pinnedness.is_pinned() {
|
||||
base_ty.pinned_ty().ok_or_else(|| {
|
||||
debug!("By-pin-ref binding of non-`Pin` type: {base_ty:?}");
|
||||
self.cx.report_bug(pat.span, "by-pin-ref binding of non-`Pin` type")
|
||||
})?
|
||||
} else {
|
||||
base_ty
|
||||
};
|
||||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
|
|
@ -1264,7 +1272,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
{
|
||||
Some(ty) => Ok(ty),
|
||||
None => {
|
||||
debug!("By-ref binding of non-derefable type");
|
||||
debug!("By-ref binding of non-derefable type: {base_ty:?}");
|
||||
Err(self
|
||||
.cx
|
||||
.report_bug(pat.span, "by-ref binding of non-derefable type"))
|
||||
|
|
@ -1706,6 +1714,18 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
};
|
||||
self.pat_deref_place(pat.hir_id, place_with_id, pat, target_ty)?
|
||||
}
|
||||
adjustment::PatAdjust::PinDeref => {
|
||||
debug!("`PinDeref` of non-pinned-reference type: {:?}", adjust.source);
|
||||
let target_ty = adjust.source.pinned_ty().ok_or_else(|| {
|
||||
self.cx.report_bug(
|
||||
self.cx.tcx().hir_span(pat.hir_id),
|
||||
"`PinDeref` of non-pinned-reference type",
|
||||
)
|
||||
})?;
|
||||
let kind = ProjectionKind::Field(FieldIdx::ZERO, FIRST_VARIANT);
|
||||
place_with_id = self.cat_projection(pat.hir_id, place_with_id, target_ty, kind);
|
||||
self.cat_deref(pat.hir_id, place_with_id)?
|
||||
}
|
||||
};
|
||||
}
|
||||
drop(typeck_results); // explicitly release borrow of typeck results, just in case.
|
||||
|
|
@ -1877,7 +1897,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
// Deref patterns on boxes are lowered using a built-in deref.
|
||||
hir::ByRef::No => self.cat_deref(hir_id, base_place),
|
||||
// For other types, we create a temporary to match on.
|
||||
hir::ByRef::Yes(mutability) => {
|
||||
hir::ByRef::Yes(_, mutability) => {
|
||||
let re_erased = self.cx.tcx().lifetimes.re_erased;
|
||||
let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability);
|
||||
// A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc_hir::{
|
|||
use rustc_hir_analysis::autoderef::report_autoderef_recursion_limit_error;
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::traits::PatternOriginExpr;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_session::parse::feature_err;
|
||||
|
|
@ -403,7 +403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
|
||||
self.write_ty(pat.hir_id, ty);
|
||||
|
||||
// If we implicitly inserted overloaded dereferences before matching, check the pattern to
|
||||
// If we implicitly inserted overloaded dereferences before matching check the pattern to
|
||||
// see if the dereferenced types need `DerefMut` bounds.
|
||||
if let Some(derefed_tys) = self.typeck_results.borrow().pat_adjustments().get(pat.hir_id)
|
||||
&& derefed_tys.iter().any(|adjust| adjust.kind == PatAdjust::OverloadedDeref)
|
||||
|
|
@ -413,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat,
|
||||
derefed_tys.iter().filter_map(|adjust| match adjust.kind {
|
||||
PatAdjust::OverloadedDeref => Some(adjust.source),
|
||||
PatAdjust::BuiltinDeref => None,
|
||||
PatAdjust::BuiltinDeref | PatAdjust::PinDeref => None,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -471,7 +471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat_info: PatInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
#[cfg(debug_assertions)]
|
||||
if pat_info.binding_mode == ByRef::Yes(Mutability::Mut)
|
||||
if matches!(pat_info.binding_mode, ByRef::Yes(_, Mutability::Mut))
|
||||
&& pat_info.max_ref_mutbl != MutblCap::Mut
|
||||
&& self.downgrade_mut_inside_shared()
|
||||
{
|
||||
|
|
@ -489,12 +489,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let old_pat_info = pat_info;
|
||||
let pat_info = PatInfo { current_depth: old_pat_info.current_depth + 1, ..old_pat_info };
|
||||
|
||||
let adjust_binding_mode = |inner_pinnedness, inner_mutability| {
|
||||
match pat_info.binding_mode {
|
||||
// If default binding mode is by value, make it `ref`, `ref mut`, `ref pin const`
|
||||
// or `ref pin mut` (depending on whether we observe `&`, `&mut`, `&pin const` or
|
||||
// `&pin mut`).
|
||||
ByRef::No => ByRef::Yes(inner_pinnedness, inner_mutability),
|
||||
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
|
||||
// Pinnedness is preserved.
|
||||
ByRef::Yes(pinnedness, Mutability::Mut) => ByRef::Yes(pinnedness, inner_mutability),
|
||||
// Once a `ref`, always a `ref`.
|
||||
// This is because a `& &mut` cannot mutate the underlying value.
|
||||
// Pinnedness is preserved.
|
||||
ByRef::Yes(pinnedness, Mutability::Not) => ByRef::Yes(pinnedness, Mutability::Not),
|
||||
}
|
||||
};
|
||||
|
||||
match pat.kind {
|
||||
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
|
||||
// Peel off a `&` or `&mut`from the scrutinee type. See the examples in
|
||||
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
|
||||
_ if let AdjustMode::Peel { kind: peel_kind } = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
|
||||
&& let &ty::Ref(_, inner_ty, inner_mutability) = expected.kind()
|
||||
&& self.should_peel_ref(peel_kind, expected) =>
|
||||
{
|
||||
debug!("inspecting {:?}", expected);
|
||||
|
|
@ -508,22 +524,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.or_default()
|
||||
.push(PatAdjustment { kind: PatAdjust::BuiltinDeref, source: expected });
|
||||
|
||||
let mut binding_mode = ByRef::Yes(match pat_info.binding_mode {
|
||||
// If default binding mode is by value, make it `ref` or `ref mut`
|
||||
// (depending on whether we observe `&` or `&mut`).
|
||||
ByRef::No |
|
||||
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
|
||||
ByRef::Yes(Mutability::Mut) => inner_mutability,
|
||||
// Once a `ref`, always a `ref`.
|
||||
// This is because a `& &mut` cannot mutate the underlying value.
|
||||
ByRef::Yes(Mutability::Not) => Mutability::Not,
|
||||
});
|
||||
let mut binding_mode = adjust_binding_mode(Pinnedness::Not, inner_mutability);
|
||||
|
||||
let mut max_ref_mutbl = pat_info.max_ref_mutbl;
|
||||
if self.downgrade_mut_inside_shared() {
|
||||
binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl());
|
||||
}
|
||||
if binding_mode == ByRef::Yes(Mutability::Not) {
|
||||
if matches!(binding_mode, ByRef::Yes(_, Mutability::Not)) {
|
||||
max_ref_mutbl = MutblCap::Not;
|
||||
}
|
||||
debug!("default binding mode is now {:?}", binding_mode);
|
||||
|
|
@ -533,6 +540,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Recurse with the new expected type.
|
||||
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
|
||||
}
|
||||
// If `pin_ergonomics` is enabled, peel the `&pin` from the pinned reference type. See the
|
||||
// examples in `tests/ui/async-await/pin-ergonomics/`.
|
||||
_ if self.tcx.features().pin_ergonomics()
|
||||
&& let AdjustMode::Peel { kind: peel_kind } = adjust_mode
|
||||
&& pat.default_binding_modes
|
||||
&& self.should_peel_smart_pointer(peel_kind, expected)
|
||||
&& let Some(pinned_ty) = expected.pinned_ty()
|
||||
// Currently, only pinned reference is specially handled, leaving other
|
||||
// pinned types (e.g. `Pin<Box<T>>` to deref patterns) handled as a
|
||||
// deref pattern.
|
||||
&& let &ty::Ref(_, inner_ty, inner_mutability) = pinned_ty.kind() =>
|
||||
{
|
||||
debug!("scrutinee ty {expected:?} is a pinned reference, inserting pin deref");
|
||||
|
||||
// if the inner_ty is an ADT, make sure that it can be structurally pinned
|
||||
// (i.e., it is `#[pin_v2]`).
|
||||
if let Some(adt) = inner_ty.ty_adt_def()
|
||||
&& !adt.is_pin_project()
|
||||
&& !adt.is_pin()
|
||||
{
|
||||
let def_span: Option<Span> = self.tcx.hir_span_if_local(adt.did());
|
||||
let sugg_span = def_span.map(|span| span.shrink_to_lo());
|
||||
self.dcx().emit_err(crate::errors::ProjectOnNonPinProjectType {
|
||||
span: pat.span,
|
||||
def_span,
|
||||
sugg_span,
|
||||
});
|
||||
}
|
||||
|
||||
let binding_mode = adjust_binding_mode(Pinnedness::Pinned, inner_mutability);
|
||||
// If the pinnedness is `Not`, it means the pattern is unpinned
|
||||
// and thus requires an `Unpin` bound.
|
||||
if matches!(binding_mode, ByRef::Yes(Pinnedness::Not, _)) {
|
||||
self.register_bound(
|
||||
inner_ty,
|
||||
self.tcx.require_lang_item(hir::LangItem::Unpin, pat.span),
|
||||
self.misc(pat.span),
|
||||
)
|
||||
}
|
||||
debug!("default binding mode is now {:?}", binding_mode);
|
||||
|
||||
// Use the old pat info to keep `current_depth` to its old value.
|
||||
let new_pat_info = PatInfo { binding_mode, ..old_pat_info };
|
||||
|
||||
self.check_deref_pattern(
|
||||
pat,
|
||||
opt_path_res,
|
||||
adjust_mode,
|
||||
expected,
|
||||
inner_ty,
|
||||
PatAdjust::PinDeref,
|
||||
new_pat_info,
|
||||
)
|
||||
}
|
||||
// If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the
|
||||
// examples in `tests/ui/pattern/deref_patterns/`.
|
||||
_ if self.tcx.features().deref_patterns()
|
||||
|
|
@ -540,35 +601,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& pat.default_binding_modes
|
||||
&& self.should_peel_smart_pointer(peel_kind, expected) =>
|
||||
{
|
||||
debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref");
|
||||
debug!("scrutinee ty {expected:?} is a smart pointer, inserting pin deref");
|
||||
|
||||
// The scrutinee is a smart pointer; implicitly dereference it. This adds a
|
||||
// requirement that `expected: DerefPure`.
|
||||
let mut inner_ty = self.deref_pat_target(pat.span, expected);
|
||||
let inner_ty = self.deref_pat_target(pat.span, expected);
|
||||
// Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
|
||||
// `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`.
|
||||
|
||||
let mut typeck_results = self.typeck_results.borrow_mut();
|
||||
let mut pat_adjustments_table = typeck_results.pat_adjustments_mut();
|
||||
let pat_adjustments = pat_adjustments_table.entry(pat.hir_id).or_default();
|
||||
// We may reach the recursion limit if a user matches on a type `T` satisfying
|
||||
// `T: Deref<Target = T>`; error gracefully in this case.
|
||||
// FIXME(deref_patterns): If `deref_patterns` stabilizes, it may make sense to move
|
||||
// this check out of this branch. Alternatively, this loop could be implemented with
|
||||
// autoderef and this check removed. For now though, don't break code compiling on
|
||||
// stable with lots of `&`s and a low recursion limit, if anyone's done that.
|
||||
if self.tcx.recursion_limit().value_within_limit(pat_adjustments.len()) {
|
||||
// Preserve the smart pointer type for THIR lowering and closure upvar analysis.
|
||||
pat_adjustments
|
||||
.push(PatAdjustment { kind: PatAdjust::OverloadedDeref, source: expected });
|
||||
} else {
|
||||
let guar = report_autoderef_recursion_limit_error(self.tcx, pat.span, expected);
|
||||
inner_ty = Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
drop(typeck_results);
|
||||
|
||||
// Recurse, using the old pat info to keep `current_depth` to its old value.
|
||||
// Peeling smart pointers does not update the default binding mode.
|
||||
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, old_pat_info)
|
||||
self.check_deref_pattern(
|
||||
pat,
|
||||
opt_path_res,
|
||||
adjust_mode,
|
||||
expected,
|
||||
inner_ty,
|
||||
PatAdjust::OverloadedDeref,
|
||||
old_pat_info,
|
||||
)
|
||||
}
|
||||
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
|
||||
// We allow any type here; we ensure that the type is uninhabited during match checking.
|
||||
|
|
@ -647,6 +696,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_deref_pattern(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
opt_path_res: Option<Result<ResolvedPat<'tcx>, ErrorGuaranteed>>,
|
||||
adjust_mode: AdjustMode,
|
||||
expected: Ty<'tcx>,
|
||||
mut inner_ty: Ty<'tcx>,
|
||||
pat_adjust_kind: PatAdjust,
|
||||
pat_info: PatInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
debug_assert!(
|
||||
!matches!(pat_adjust_kind, PatAdjust::BuiltinDeref),
|
||||
"unexpected deref pattern for builtin reference type {expected:?}",
|
||||
);
|
||||
|
||||
let mut typeck_results = self.typeck_results.borrow_mut();
|
||||
let mut pat_adjustments_table = typeck_results.pat_adjustments_mut();
|
||||
let pat_adjustments = pat_adjustments_table.entry(pat.hir_id).or_default();
|
||||
// We may reach the recursion limit if a user matches on a type `T` satisfying
|
||||
// `T: Deref<Target = T>`; error gracefully in this case.
|
||||
// FIXME(deref_patterns): If `deref_patterns` stabilizes, it may make sense to move
|
||||
// this check out of this branch. Alternatively, this loop could be implemented with
|
||||
// autoderef and this check removed. For now though, don't break code compiling on
|
||||
// stable with lots of `&`s and a low recursion limit, if anyone's done that.
|
||||
if self.tcx.recursion_limit().value_within_limit(pat_adjustments.len()) {
|
||||
// Preserve the smart pointer type for THIR lowering and closure upvar analysis.
|
||||
pat_adjustments.push(PatAdjustment { kind: pat_adjust_kind, source: expected });
|
||||
} else {
|
||||
let guar = report_autoderef_recursion_limit_error(self.tcx, pat.span, expected);
|
||||
inner_ty = Ty::new_error(self.tcx, guar);
|
||||
}
|
||||
drop(typeck_results);
|
||||
|
||||
// Recurse, using the old pat info to keep `current_depth` to its old value.
|
||||
// Peeling smart pointers does not update the default binding mode.
|
||||
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, pat_info)
|
||||
}
|
||||
|
||||
/// How should the binding mode and expected type be adjusted?
|
||||
///
|
||||
/// When the pattern contains a path, `opt_path_res` must be `Some(path_res)`.
|
||||
|
|
@ -1061,7 +1148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Determine the binding mode...
|
||||
let bm = match user_bind_annot {
|
||||
BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => {
|
||||
BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(_, def_br_mutbl) = def_br => {
|
||||
// Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
|
||||
// using other experimental matching features compatible with it.
|
||||
if pat.span.at_least_rust_2024()
|
||||
|
|
@ -1091,8 +1178,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
|
||||
BindingMode(ByRef::Yes(user_br_mutbl), _) => {
|
||||
if let ByRef::Yes(def_br_mutbl) = def_br {
|
||||
BindingMode(ByRef::Yes(_, user_br_mutbl), _) => {
|
||||
if let ByRef::Yes(_, def_br_mutbl) = def_br {
|
||||
// `ref`/`ref mut` overrides the binding mode on edition <= 2021
|
||||
self.add_rust_2024_migration_desugared_pat(
|
||||
pat_info.top_info.hir_id,
|
||||
|
|
@ -1108,7 +1195,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
if bm.0 == ByRef::Yes(Mutability::Mut)
|
||||
if matches!(bm.0, ByRef::Yes(_, Mutability::Mut))
|
||||
&& let MutblCap::WeaklyNot(and_pat_span) = pat_info.max_ref_mutbl
|
||||
{
|
||||
let mut err = struct_span_code_err!(
|
||||
|
|
@ -1136,7 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let local_ty = self.local_ty(pat.span, pat.hir_id);
|
||||
let eq_ty = match bm.0 {
|
||||
ByRef::Yes(mutbl) => {
|
||||
ByRef::Yes(Pinnedness::Not, mutbl) => {
|
||||
// If the binding is like `ref x | ref mut x`,
|
||||
// then `x` is assigned a value of type `&M T` where M is the
|
||||
// mutability and T is the expected type.
|
||||
|
|
@ -1146,6 +1233,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// See (note_1) for an explanation.
|
||||
self.new_ref_ty(pat.span, mutbl, expected)
|
||||
}
|
||||
// Wrapping the type into `Pin` if the binding is like `ref pin const|mut x`
|
||||
ByRef::Yes(Pinnedness::Pinned, mutbl) => Ty::new_adt(
|
||||
self.tcx,
|
||||
self.tcx.adt_def(self.tcx.require_lang_item(hir::LangItem::Pin, pat.span)),
|
||||
self.tcx.mk_args(&[self.new_ref_ty(pat.span, mutbl, expected).into()]),
|
||||
),
|
||||
// Otherwise, the type of x is the expected type `T`.
|
||||
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
|
||||
};
|
||||
|
|
@ -2605,7 +2698,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expected = self.try_structurally_resolve_type(pat.span, expected);
|
||||
// Determine whether we're consuming an inherited reference and resetting the default
|
||||
// binding mode, based on edition and enabled experimental features.
|
||||
if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
|
||||
if let ByRef::Yes(inh_pin, inh_mut) = pat_info.binding_mode
|
||||
// FIXME(pin_ergonomics): since `&pin` pattern is supported, the condition here
|
||||
// should be adjusted to `pat_pin == inh_pin`
|
||||
&& (!self.tcx.features().pin_ergonomics() || inh_pin == Pinnedness::Not)
|
||||
{
|
||||
match self.ref_pat_matches_inherited_ref(pat.span.edition()) {
|
||||
InheritedRefMatchRule::EatOuter => {
|
||||
// ref pattern attempts to consume inherited reference
|
||||
|
|
@ -3126,8 +3223,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// If the user-provided binding modifier doesn't match the default binding mode, we'll
|
||||
// need to suggest reference patterns, which can affect other bindings.
|
||||
// For simplicity, we opt to suggest making the pattern fully explicit.
|
||||
info.suggest_eliding_modes &=
|
||||
user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
|
||||
info.suggest_eliding_modes &= matches!(
|
||||
user_bind_annot,
|
||||
BindingMode(ByRef::Yes(_, mutbl), Mutability::Not) if mutbl == def_br_mutbl
|
||||
);
|
||||
if user_bind_annot == BindingMode(ByRef::No, Mutability::Mut) {
|
||||
info.bad_mut_modifiers = true;
|
||||
"`mut` binding modifier"
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs {
|
|||
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) {
|
||||
if let hir::StmtKind::Let(loc) = stmt.kind
|
||||
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
|
||||
&& let hir::ByRef::Yes(m) = ba.0
|
||||
&& let hir::ByRef::Yes(_, m) = ba.0
|
||||
&& let Some(init) = loc.init
|
||||
&& let Some(err_span) = path_is_static_mut(init, init.span)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -232,4 +232,7 @@ pub enum PatAdjust {
|
|||
/// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the
|
||||
/// pattern `[..]` against a scrutinee of type `Vec<T>`.
|
||||
OverloadedDeref,
|
||||
/// An implicit dereference before matching a `&pin` reference (under feature `pin_ergonomics`),
|
||||
/// which will be lowered as a builtin deref of the private field `__pointer` in `Pin`
|
||||
PinDeref,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ bitflags::bitflags! {
|
|||
const IS_UNSAFE_CELL = 1 << 9;
|
||||
/// Indicates whether the type is `UnsafePinned`.
|
||||
const IS_UNSAFE_PINNED = 1 << 10;
|
||||
/// Indicates whether the type is `Pin`.
|
||||
const IS_PIN = 1 << 11;
|
||||
/// Indicates whether the type is `#[pin_project]`.
|
||||
const IS_PIN_PROJECT = 1 << 12;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { AdtFlags }
|
||||
|
|
@ -284,6 +288,10 @@ impl AdtDefData {
|
|||
debug!("found non-exhaustive variant list for {:?}", did);
|
||||
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
|
||||
}
|
||||
if find_attr!(tcx.get_all_attrs(did), AttributeKind::PinV2(..)) {
|
||||
debug!("found pin-project type {:?}", did);
|
||||
flags |= AdtFlags::IS_PIN_PROJECT;
|
||||
}
|
||||
|
||||
flags |= match kind {
|
||||
AdtKind::Enum => AdtFlags::IS_ENUM,
|
||||
|
|
@ -313,6 +321,9 @@ impl AdtDefData {
|
|||
if tcx.is_lang_item(did, LangItem::UnsafePinned) {
|
||||
flags |= AdtFlags::IS_UNSAFE_PINNED;
|
||||
}
|
||||
if tcx.is_lang_item(did, LangItem::Pin) {
|
||||
flags |= AdtFlags::IS_PIN;
|
||||
}
|
||||
|
||||
AdtDefData { did, variants, flags, repr }
|
||||
}
|
||||
|
|
@ -428,6 +439,19 @@ impl<'tcx> AdtDef<'tcx> {
|
|||
self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is `Pin<T>`.
|
||||
#[inline]
|
||||
pub fn is_pin(self) -> bool {
|
||||
self.flags().contains(AdtFlags::IS_PIN)
|
||||
}
|
||||
|
||||
/// Returns `true` is this is `#[pin_v2]` for the purposes
|
||||
/// of structural pinning.
|
||||
#[inline]
|
||||
pub fn is_pin_project(self) -> bool {
|
||||
self.flags().contains(AdtFlags::IS_PIN_PROJECT)
|
||||
}
|
||||
|
||||
/// Returns `true` if this type has a destructor.
|
||||
pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.destructor(tcx).is_some()
|
||||
|
|
|
|||
|
|
@ -1349,6 +1349,23 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pinned_ty(self) -> Option<Ty<'tcx>> {
|
||||
match self.kind() {
|
||||
Adt(def, args) if def.is_pin() => Some(args.type_at(0)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pinned_ref(self) -> Option<(Ty<'tcx>, ty::Mutability)> {
|
||||
if let Adt(def, args) = self.kind()
|
||||
&& def.is_pin()
|
||||
&& let &ty::Ref(_, ty, mutbl) = args.type_at(0).kind()
|
||||
{
|
||||
return Some((ty, mutbl));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Panics if called on any type other than `Box<T>`.
|
||||
pub fn expect_boxed_ty(self) -> Ty<'tcx> {
|
||||
self.boxed_ty()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
|
|||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_hir::{
|
||||
self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
|
||||
Pinnedness,
|
||||
};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||
|
|
@ -479,7 +480,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||
let mut has_ref_mut = false;
|
||||
pat.walk(|pat| {
|
||||
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
|
||||
&& let Some(BindingMode(ByRef::Yes(Mutability::Mut), _)) =
|
||||
&& let Some(BindingMode(ByRef::Yes(_, Mutability::Mut), _)) =
|
||||
self.pat_binding_modes().get(id)
|
||||
{
|
||||
has_ref_mut = true;
|
||||
|
|
@ -503,7 +504,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
|||
ByRef::No
|
||||
} else {
|
||||
let mutable = self.pat_has_ref_mut_binding(inner);
|
||||
ByRef::Yes(if mutable { Mutability::Mut } else { Mutability::Not })
|
||||
ByRef::Yes(Pinnedness::Not, if mutable { Mutability::Mut } else { Mutability::Not })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_hir::ByRef;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
|
||||
|
|
@ -299,7 +300,24 @@ impl<'tcx> MatchPairTree<'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
PatKind::DerefPattern { ref subpattern, borrow: ByRef::Yes(mutability) } => {
|
||||
PatKind::DerefPattern { ref subpattern, borrow: ByRef::Yes(Pinnedness::Pinned, _) } => {
|
||||
let Some(ref_ty) = pattern.ty.pinned_ty() else {
|
||||
rustc_middle::bug!("RefPin pattern on non-`Pin` type {:?}", pattern.ty);
|
||||
};
|
||||
MatchPairTree::for_pattern(
|
||||
place_builder.field(FieldIdx::ZERO, ref_ty).deref(),
|
||||
subpattern,
|
||||
cx,
|
||||
&mut subpairs,
|
||||
extra_data,
|
||||
);
|
||||
None
|
||||
}
|
||||
|
||||
PatKind::DerefPattern {
|
||||
ref subpattern,
|
||||
borrow: ByRef::Yes(Pinnedness::Not, mutability),
|
||||
} => {
|
||||
// Create a new temporary for each deref pattern.
|
||||
// FIXME(deref_patterns): dedup temporaries to avoid multiple `deref()` calls?
|
||||
let temp = cx.temp(
|
||||
|
|
|
|||
|
|
@ -5,20 +5,21 @@
|
|||
//! This also includes code for pattern bindings in `let` statements and
|
||||
//! function parameters.
|
||||
|
||||
use std::assert_matches::debug_assert_matches;
|
||||
use std::borrow::Borrow;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_abi::VariantIdx;
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::{BindingMode, ByRef, LetStmt, LocalSource, Node};
|
||||
use rustc_middle::bug;
|
||||
use rustc_hir::{BindingMode, ByRef, LangItem, LetStmt, LocalSource, Node, Pinnedness};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{self, *};
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, ValTree, ValTreeKind};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_pattern_analysis::constructor::RangeEnd;
|
||||
use rustc_pattern_analysis::rustc::{DeconstructedPat, RustcPatCtxt};
|
||||
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
|
||||
|
|
@ -917,6 +918,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
visit_subpat(self, subpattern, &user_tys.deref(), f);
|
||||
}
|
||||
|
||||
PatKind::DerefPattern { ref subpattern, borrow: ByRef::Yes(Pinnedness::Pinned, _) } => {
|
||||
visit_subpat(self, subpattern, &user_tys.leaf(FieldIdx::ZERO).deref(), f);
|
||||
}
|
||||
|
||||
PatKind::DerefPattern { ref subpattern, .. } => {
|
||||
visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
|
||||
}
|
||||
|
|
@ -2747,9 +2752,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, binding.source);
|
||||
self.cfg.push_assign(block, source_info, ref_for_guard, rvalue);
|
||||
}
|
||||
ByRef::Yes(mutbl) => {
|
||||
// The arm binding will be by reference, so eagerly create it now. Drops must
|
||||
// be scheduled to emit `StorageDead` on the guard's failure/break branches.
|
||||
ByRef::Yes(pinnedness, mutbl) => {
|
||||
// The arm binding will be by reference, so eagerly create it now // be scheduled to emit `StorageDead` on the guard's failure/break branches.
|
||||
let value_for_arm = self.storage_live_binding(
|
||||
block,
|
||||
binding.var_id,
|
||||
|
|
@ -2761,6 +2765,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
let rvalue =
|
||||
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
|
||||
let rvalue = match pinnedness {
|
||||
ty::Pinnedness::Not => rvalue,
|
||||
ty::Pinnedness::Pinned => {
|
||||
self.pin_borrowed_local(block, value_for_arm.local, rvalue, source_info)
|
||||
}
|
||||
};
|
||||
self.cfg.push_assign(block, source_info, value_for_arm, rvalue);
|
||||
// For the guard binding, take a shared reference to that reference.
|
||||
let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, value_for_arm);
|
||||
|
|
@ -2797,14 +2807,59 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
let rvalue = match binding.binding_mode.0 {
|
||||
ByRef::No => Rvalue::Use(self.consume_by_copy_or_move(binding.source)),
|
||||
ByRef::Yes(mutbl) => {
|
||||
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source)
|
||||
ByRef::Yes(pinnedness, mutbl) => {
|
||||
let rvalue =
|
||||
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
|
||||
match pinnedness {
|
||||
ty::Pinnedness::Not => rvalue,
|
||||
ty::Pinnedness::Pinned => {
|
||||
self.pin_borrowed_local(block, local.local, rvalue, source_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
self.cfg.push_assign(block, source_info, local, rvalue);
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an rvalue `&[mut]borrow` and a local `local`, generate the pinned borrow for it:
|
||||
/// ```ignore (illustrative)
|
||||
/// pinned_temp = &borrow;
|
||||
/// local = Pin { __pointer: move pinned_temp };
|
||||
/// ```
|
||||
fn pin_borrowed_local(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
local: Local,
|
||||
borrow: Rvalue<'tcx>,
|
||||
source_info: SourceInfo,
|
||||
) -> Rvalue<'tcx> {
|
||||
debug_assert_matches!(borrow, Rvalue::Ref(..));
|
||||
|
||||
let local_ty = self.local_decls[local].ty;
|
||||
|
||||
let pinned_ty = local_ty.pinned_ty().unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
source_info.span,
|
||||
"expect type `Pin` for a pinned binding, found type {:?}",
|
||||
local_ty
|
||||
)
|
||||
});
|
||||
let pinned_temp =
|
||||
Place::from(self.local_decls.push(LocalDecl::new(pinned_ty, source_info.span)));
|
||||
self.cfg.push_assign(block, source_info, pinned_temp, borrow);
|
||||
Rvalue::Aggregate(
|
||||
Box::new(AggregateKind::Adt(
|
||||
self.tcx.require_lang_item(LangItem::Pin, source_info.span),
|
||||
FIRST_VARIANT,
|
||||
self.tcx.mk_args(&[pinned_ty.into()]),
|
||||
None,
|
||||
None,
|
||||
)),
|
||||
std::iter::once(Operand::Move(pinned_temp)).collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Each binding (`ref mut var`/`ref var`/`mut var`/`var`, where the bound
|
||||
/// `var` has type `T` in the arm body) in a pattern maps to 2 locals. The
|
||||
/// first local is a binding for occurrences of `var` in the guard, which
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
visit::walk_pat(self, pat);
|
||||
}
|
||||
PatKind::Binding { mode: BindingMode(ByRef::Yes(rm), _), ty, .. } => {
|
||||
PatKind::Binding { mode: BindingMode(ByRef::Yes(_, rm), _), ty, .. } => {
|
||||
if self.inside_adt {
|
||||
let ty::Ref(_, ty, _) = ty.kind() else {
|
||||
span_bug!(
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
// We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
|
||||
let mut conflicts_ref = Vec::new();
|
||||
sub.each_binding(|_, mode, _, span| {
|
||||
if matches!(mode, ByRef::Yes(_)) {
|
||||
if matches!(mode, ByRef::Yes(..)) {
|
||||
conflicts_ref.push(span)
|
||||
}
|
||||
});
|
||||
|
|
@ -813,7 +813,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
return;
|
||||
}
|
||||
ByRef::No => return,
|
||||
ByRef::Yes(m) => m,
|
||||
ByRef::Yes(_, m) => m,
|
||||
};
|
||||
|
||||
// We now have `ref $mut_outer binding @ sub` (semantically).
|
||||
|
|
@ -823,7 +823,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
let mut conflicts_mut_ref = Vec::new();
|
||||
sub.each_binding(|name, mode, ty, span| {
|
||||
match mode {
|
||||
ByRef::Yes(mut_inner) => match (mut_outer, mut_inner) {
|
||||
ByRef::Yes(_, mut_inner) => match (mut_outer, mut_inner) {
|
||||
// Both sides are `ref`.
|
||||
(Mutability::Not, Mutability::Not) => {}
|
||||
// 2x `ref mut`.
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ impl<'a> PatMigration<'a> {
|
|||
}
|
||||
if !self.info.suggest_eliding_modes
|
||||
&& explicit_ba.0 == ByRef::No
|
||||
&& let ByRef::Yes(mutbl) = mode.0
|
||||
&& let ByRef::Yes(_, mutbl) = mode.0
|
||||
{
|
||||
// If we can't fix the pattern by eliding modifiers, we'll need to make the pattern
|
||||
// fully explicit. i.e. we'll need to suggest reference patterns for this.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer};
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc_hir::{self as hir, LangItem, RangeEnd};
|
||||
use rustc_hir::{self as hir, ByRef, LangItem, Mutability, Pinnedness, RangeEnd};
|
||||
use rustc_index::Idx;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::mir::interpret::LitToConstInput;
|
||||
|
|
@ -114,6 +114,16 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
let borrow = self.typeck_results.deref_pat_borrow_mode(adjust.source, pat);
|
||||
PatKind::DerefPattern { subpattern: thir_pat, borrow }
|
||||
}
|
||||
PatAdjust::PinDeref => {
|
||||
let mutable = self.typeck_results.pat_has_ref_mut_binding(pat);
|
||||
PatKind::DerefPattern {
|
||||
subpattern: thir_pat,
|
||||
borrow: ByRef::Yes(
|
||||
Pinnedness::Pinned,
|
||||
if mutable { Mutability::Mut } else { Mutability::Not },
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
Box::new(Pat { span, ty: adjust.source, kind })
|
||||
});
|
||||
|
|
@ -354,11 +364,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
// A ref x pattern is the same node used for x, and as such it has
|
||||
// x's type, which is &T, where we want T (the type being matched).
|
||||
let var_ty = ty;
|
||||
if let hir::ByRef::Yes(_) = mode.0 {
|
||||
if let ty::Ref(_, rty, _) = ty.kind() {
|
||||
ty = *rty;
|
||||
} else {
|
||||
bug!("`ref {}` has wrong type {}", ident, ty);
|
||||
if let hir::ByRef::Yes(pinnedness, _) = mode.0 {
|
||||
match pinnedness {
|
||||
hir::Pinnedness::Pinned
|
||||
if let Some(pty) = ty.pinned_ty()
|
||||
&& let &ty::Ref(_, rty, _) = pty.kind() =>
|
||||
{
|
||||
debug_assert!(
|
||||
self.tcx.features().pin_ergonomics(),
|
||||
"`pin_ergonomics` must be enabled to have a by-pin-ref binding"
|
||||
);
|
||||
ty = rty;
|
||||
}
|
||||
hir::Pinnedness::Not if let &ty::Ref(_, rty, _) = ty.kind() => {
|
||||
ty = rty;
|
||||
}
|
||||
_ => bug!("`ref {}` has wrong type {}", ident, ty),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ use rustc_ast::tokenstream::{
|
|||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
|
||||
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit,
|
||||
Visibility, VisibilityKind,
|
||||
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Pinnedness, Recovered,
|
||||
Safety, StrLit, Visibility, VisibilityKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -1317,7 +1317,12 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses reference binding mode (`ref`, `ref mut`, or nothing).
|
||||
fn parse_byref(&mut self) -> ByRef {
|
||||
if self.eat_keyword(exp!(Ref)) { ByRef::Yes(self.parse_mutability()) } else { ByRef::No }
|
||||
if self.eat_keyword(exp!(Ref)) {
|
||||
// FIXME(pin_ergonomics): support `ref pin const|mut` bindings
|
||||
ByRef::Yes(Pinnedness::Not, self.parse_mutability())
|
||||
} else {
|
||||
ByRef::No
|
||||
}
|
||||
}
|
||||
|
||||
/// Possibly parses mutability (`const` or `mut`).
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use rustc_ast::util::parser::ExprPrecedence;
|
|||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::{
|
||||
self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
|
||||
Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
|
||||
Pat, PatField, PatFieldsRest, PatKind, Path, Pinnedness, QSelf, RangeEnd, RangeSyntax, Stmt,
|
||||
StmtKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
|
||||
|
|
@ -778,7 +779,11 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
// Parse ref ident @ pat / ref mut ident @ pat
|
||||
let mutbl = self.parse_mutability();
|
||||
self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)?
|
||||
self.parse_pat_ident(
|
||||
// FIXME(pin_ergonomics): support `ref pin const|mut` bindings
|
||||
BindingMode(ByRef::Yes(Pinnedness::Not, mutbl), Mutability::Not),
|
||||
syntax_loc,
|
||||
)?
|
||||
} else if self.eat_keyword(exp!(Box)) {
|
||||
self.parse_pat_box()?
|
||||
} else if self.check_inline_const(0) {
|
||||
|
|
@ -1093,7 +1098,7 @@ impl<'a> Parser<'a> {
|
|||
self.ban_mut_general_pat(mut_span, &pat, changed_any_binding);
|
||||
}
|
||||
|
||||
if matches!(pat.kind, PatKind::Ident(BindingMode(ByRef::Yes(_), Mutability::Mut), ..)) {
|
||||
if matches!(pat.kind, PatKind::Ident(BindingMode(ByRef::Yes(..), Mutability::Mut), ..)) {
|
||||
self.psess.gated_spans.gate(sym::mut_ref, pat.span);
|
||||
}
|
||||
Ok(pat.kind)
|
||||
|
|
|
|||
|
|
@ -283,7 +283,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::ObjcSelector { .. }
|
||||
| AttributeKind::RustcCoherenceIsCore(..)
|
||||
| AttributeKind::DebuggerVisualizer(..)
|
||||
| AttributeKind::RustcMain,
|
||||
| AttributeKind::RustcMain
|
||||
| AttributeKind::PinV2(..),
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
|
|
|
|||
|
|
@ -1668,6 +1668,7 @@ symbols! {
|
|||
pin,
|
||||
pin_ergonomics,
|
||||
pin_macro,
|
||||
pin_v2,
|
||||
platform_intrinsics,
|
||||
plugin,
|
||||
plugin_registrar,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<Hir
|
|||
// We'll just ignore mut and ref mut for simplicity sake right now
|
||||
if let hir::PatKind::Binding(hir::BindingMode(by_ref, hir::Mutability::Not), value_hir_id, ident, sub_pat) =
|
||||
pat.kind
|
||||
&& by_ref != hir::ByRef::Yes(hir::Mutability::Mut)
|
||||
&& !matches!(by_ref, hir::ByRef::Yes(_, hir::Mutability::Mut))
|
||||
{
|
||||
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
|
||||
// for them and it's likely that the user knows what they are doing in such a case.
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
|
|||
.qpath_res(qpath, arm.pat.hir_id)
|
||||
.ctor_parent(cx)
|
||||
.is_lang_item(cx, LangItem::OptionSome)
|
||||
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind
|
||||
&& let PatKind::Binding(BindingMode(ByRef::Yes(_, mutabl), _), .., ident, _) = first_pat.kind
|
||||
&& let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
|
||||
&& e.res(cx).ctor_parent(cx).is_lang_item(cx, LangItem::OptionSome)
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
|
|||
},
|
||||
)),
|
||||
) => {
|
||||
return !matches!(annot, BindingMode(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name;
|
||||
return !matches!(annot, BindingMode(ByRef::Yes(..), _)) && pat_ident.name == first_seg.ident.name;
|
||||
},
|
||||
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
|
||||
(
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ fn get_pat_binding<'tcx>(
|
|||
if let PatKind::Binding(bind_annot, hir_id, ident, _) = pat.kind
|
||||
&& hir_id == local
|
||||
{
|
||||
if matches!(bind_annot.0, rustc_ast::ByRef::Yes(_)) {
|
||||
if matches!(bind_annot.0, rustc_ast::ByRef::Yes(..)) {
|
||||
let _ = byref_ident.insert(ident);
|
||||
}
|
||||
// the second call of `replace()` returns a `Some(span)`, meaning a multi-binding pattern
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>)
|
|||
_ => false,
|
||||
},
|
||||
// local binding capturing a reference
|
||||
Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..)) => {
|
||||
Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingMode(ByRef::Yes(..), _), ..)) => {
|
||||
return;
|
||||
},
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
|
|||
let init_expr_str = Sugg::hir_with_applicability(cx, init_expr, "..", &mut applicability).maybe_paren();
|
||||
// Take care when binding is `ref`
|
||||
let sugg = if let PatKind::Binding(
|
||||
BindingMode(ByRef::Yes(ref_mutability), binding_mutability),
|
||||
BindingMode(ByRef::Yes(_,ref_mutability), binding_mutability),
|
||||
_hir_id,
|
||||
ident,
|
||||
subpattern,
|
||||
|
|
@ -169,7 +169,7 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
|
|||
// Handle subpattern (@ subpattern)
|
||||
let maybe_subpattern = match subpattern {
|
||||
Some(Pat {
|
||||
kind: PatKind::Binding(BindingMode(ByRef::Yes(_), _), _, subident, None),
|
||||
kind: PatKind::Binding(BindingMode(ByRef::Yes(..), _), _, subident, None),
|
||||
..
|
||||
}) => {
|
||||
// avoid `&ref`
|
||||
|
|
@ -504,8 +504,8 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
|
|||
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
||||
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
|
||||
let method_call_str = match by_ref {
|
||||
ByRef::Yes(Mutability::Mut) => ".as_mut()",
|
||||
ByRef::Yes(Mutability::Not) => ".as_ref()",
|
||||
ByRef::Yes(_, Mutability::Mut) => ".as_mut()",
|
||||
ByRef::Yes(_, Mutability::Not) => ".as_ref()",
|
||||
ByRef::No => "",
|
||||
};
|
||||
let sugg = format!(
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ToplevelRefArg {
|
|||
) {
|
||||
if !matches!(k, FnKind::Closure) {
|
||||
for arg in iter_input_pats(decl, body) {
|
||||
if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind
|
||||
if let PatKind::Binding(BindingMode(ByRef::Yes(..), _), ..) = arg.pat.kind
|
||||
&& is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id)
|
||||
&& !arg.span.in_external_macro(cx.tcx.sess.source_map())
|
||||
{
|
||||
|
|
@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ToplevelRefArg {
|
|||
|
||||
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
|
||||
if let StmtKind::Let(local) = stmt.kind
|
||||
&& let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind
|
||||
&& let PatKind::Binding(BindingMode(ByRef::Yes(_, mutabl), _), .., name, None) = local.pat.kind
|
||||
&& let Some(init) = local.init
|
||||
// Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
|
||||
&& is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id)
|
||||
|
|
|
|||
|
|
@ -743,10 +743,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
let ann = match ann {
|
||||
BindingMode::NONE => "NONE",
|
||||
BindingMode::REF => "REF",
|
||||
BindingMode::REF_PIN => "REF_PIN",
|
||||
BindingMode::MUT => "MUT",
|
||||
BindingMode::REF_MUT => "REF_MUT",
|
||||
BindingMode::REF_PIN_MUT => "REF_PIN_MUT",
|
||||
BindingMode::MUT_REF => "MUT_REF",
|
||||
BindingMode::MUT_REF_PIN => "MUT_REF_PIN",
|
||||
BindingMode::MUT_REF_MUT => "MUT_REF_MUT",
|
||||
BindingMode::MUT_REF_PIN_MUT => "MUT_REF_PIN_MUT",
|
||||
};
|
||||
kind!("Binding(BindingMode::{ann}, _, {name}, {sub})");
|
||||
self.ident(name);
|
||||
|
|
|
|||
|
|
@ -211,7 +211,12 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
|||
|
||||
// Custom `Deref` impl might have side effects
|
||||
ExprKind::Unary(UnOp::Deref, e)
|
||||
if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() =>
|
||||
if self
|
||||
.cx
|
||||
.typeck_results()
|
||||
.expr_ty(e)
|
||||
.builtin_deref(true)
|
||||
.is_none() =>
|
||||
{
|
||||
self.eagerness |= NoChange;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -782,7 +782,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
|||
ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
|
||||
capture = CaptureKind::Value;
|
||||
},
|
||||
ByRef::Yes(Mutability::Mut) if capture != CaptureKind::Value => {
|
||||
ByRef::Yes(_, Mutability::Mut) if capture != CaptureKind::Value => {
|
||||
capture = CaptureKind::Ref(Mutability::Mut);
|
||||
},
|
||||
_ => (),
|
||||
|
|
@ -1830,7 +1830,7 @@ pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<
|
|||
.typeck_results()
|
||||
.pat_binding_modes()
|
||||
.get(pat.hir_id)
|
||||
.is_some_and(|mode| matches!(mode.0, ByRef::Yes(_)))
|
||||
.is_some_and(|mode| matches!(mode.0, ByRef::Yes(..)))
|
||||
{
|
||||
// If the parameter is `(x, y)` of type `&(T, T)`, or `[x, y]` of type `&[T; 2]`, then
|
||||
// due to match ergonomics, the inner patterns become references. Don't consider this
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@ impl Rewrite for Pat {
|
|||
let mut_prefix = format_mutability(mutability).trim();
|
||||
|
||||
let (ref_kw, mut_infix) = match by_ref {
|
||||
ByRef::Yes(rmutbl) => ("ref", format_mutability(rmutbl).trim()),
|
||||
// FIXME(pin_ergonomics): format the pinnedness
|
||||
ByRef::Yes(_, rmutbl) => ("ref", format_mutability(rmutbl).trim()),
|
||||
ByRef::No => ("", ""),
|
||||
};
|
||||
let id_str = rewrite_ident(context, ident);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
use std::pin::Pin;
|
||||
|
||||
#[pin_v2] //~ ERROR the `#[pin_v2]` attribute is an experimental feature
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(self: Pin<&mut Self>) {
|
||||
}
|
||||
fn foo(self: Pin<&mut Self>) {}
|
||||
fn foo_sugar(&pin mut self) {} //~ ERROR pinned reference syntax is experimental
|
||||
fn foo_sugar_const(&pin const self) {} //~ ERROR pinned reference syntax is experimental
|
||||
}
|
||||
|
|
@ -51,11 +51,11 @@ fn borrows() {
|
|||
mod not_compiled {
|
||||
use std::pin::Pin;
|
||||
|
||||
#[pin_v2]
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(self: Pin<&mut Self>) {
|
||||
}
|
||||
fn foo(self: Pin<&mut Self>) {}
|
||||
fn foo_sugar(&pin mut self) {} //~ ERROR pinned reference syntax is experimental
|
||||
fn foo_sugar_const(&pin const self) {} //~ ERROR pinned reference syntax is experimental
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,16 @@ LL | let x: Pin<&_> = &pin const Foo;
|
|||
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[pin_v2]` attribute is an experimental feature
|
||||
--> $DIR/feature-gate-pin_ergonomics.rs:5:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
|
||||
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/feature-gate-pin_ergonomics.rs:28:9
|
||||
|
|
||||
|
|
@ -177,16 +187,16 @@ LL | x.foo();
|
|||
| ^ value used here after move
|
||||
|
|
||||
note: `Foo::foo` takes ownership of the receiver `self`, which moves `x`
|
||||
--> $DIR/feature-gate-pin_ergonomics.rs:8:12
|
||||
--> $DIR/feature-gate-pin_ergonomics.rs:9:12
|
||||
|
|
||||
LL | fn foo(self: Pin<&mut Self>) {
|
||||
LL | fn foo(self: Pin<&mut Self>) {}
|
||||
| ^^^^
|
||||
help: consider reborrowing the `Pin` instead of moving it
|
||||
|
|
||||
LL | x.as_mut().foo();
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0658.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:48:28
|
||||
|
|
||||
LL | let Foo { x, y } = foo.as_mut();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { ref x, y } = foo.as_mut();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { x, ref y } = foo.as_mut();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:38:24
|
||||
|
|
||||
LL | let Foo { x, y } = foo.as_mut();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { ref x, y } = foo.as_mut();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { x, ref y } = foo.as_mut();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:70:28
|
||||
|
|
||||
LL | let Foo { x, y } = foo.as_ref();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { ref x, y } = foo.as_ref();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { x, ref y } = foo.as_ref();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:60:24
|
||||
|
|
||||
LL | let Foo { x, y } = foo.as_ref();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { ref x, y } = foo.as_ref();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Foo { x, ref y } = foo.as_ref();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:92:25
|
||||
|
|
||||
LL | let Bar(x, y) = bar.as_mut();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(ref x, y) = bar.as_mut();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(x, ref y) = bar.as_mut();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:82:21
|
||||
|
|
||||
LL | let Bar(x, y) = bar.as_mut();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(ref x, y) = bar.as_mut();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(x, ref y) = bar.as_mut();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:114:25
|
||||
|
|
||||
LL | let Bar(x, y) = bar.as_ref();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(ref x, y) = bar.as_ref();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(x, ref y) = bar.as_ref();
|
||||
| +++
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/pattern-matching-deref-pattern.rs:104:21
|
||||
|
|
||||
LL | let Bar(x, y) = bar.as_ref();
|
||||
| - - ^^^^^^^^^^^^
|
||||
| | |
|
||||
| | ...and here
|
||||
| data moved here
|
||||
|
|
||||
= note: move occurs because these variables have types that don't implement the `Copy` trait
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(ref x, y) = bar.as_ref();
|
||||
| +++
|
||||
help: consider borrowing the pattern binding
|
||||
|
|
||||
LL | let Bar(x, ref y) = bar.as_ref();
|
||||
| +++
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0507`.
|
||||
124
tests/ui/pin-ergonomics/pattern-matching-deref-pattern.rs
Normal file
124
tests/ui/pin-ergonomics/pattern-matching-deref-pattern.rs
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
//@ revisions: pin_ergonomics normal
|
||||
//@ edition:2024
|
||||
//@[pin_ergonomics] check-pass
|
||||
#![cfg_attr(pin_ergonomics, feature(pin_ergonomics))]
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// This test verifies that the `pin_ergonomics` feature works well
|
||||
// together with the `deref_patterns` feature.
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
#[cfg_attr(pin_ergonomics, pin_v2)]
|
||||
struct Foo<T, U> {
|
||||
x: T,
|
||||
y: U,
|
||||
}
|
||||
|
||||
#[cfg_attr(pin_ergonomics, pin_v2)]
|
||||
struct Bar<T, U>(T, U);
|
||||
|
||||
#[cfg_attr(pin_ergonomics, pin_v2)]
|
||||
enum Baz<T, U> {
|
||||
Foo(T, U),
|
||||
Bar { x: T, y: U },
|
||||
}
|
||||
|
||||
trait IsPinMut {}
|
||||
trait IsPinConst {}
|
||||
impl<T: ?Sized> IsPinMut for Pin<&mut T> {}
|
||||
impl<T: ?Sized> IsPinConst for Pin<&T> {}
|
||||
|
||||
fn assert_pin_mut<T: IsPinMut>(_: T) {}
|
||||
fn assert_pin_const<T: IsPinConst>(_: T) {}
|
||||
|
||||
fn foo_mut<T: Unpin, U: Unpin>(mut foo: Pin<&mut Foo<T, U>>) {
|
||||
let Foo { .. } = foo.as_mut();
|
||||
let Foo { x, y } = foo.as_mut();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(y);
|
||||
let Pin { .. } = foo.as_mut();
|
||||
|
||||
let _ = || {
|
||||
let Foo { .. } = foo.as_mut();
|
||||
let Foo { x, y } = foo.as_mut();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(y);
|
||||
let Pin { .. } = foo.as_mut();
|
||||
};
|
||||
}
|
||||
|
||||
fn foo_const<T: Unpin, U: Unpin>(foo: Pin<&Foo<T, U>>) {
|
||||
let Foo { .. } = foo.as_ref();
|
||||
let Foo { x, y } = foo.as_ref();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(y);
|
||||
let Pin { .. } = foo.as_ref();
|
||||
|
||||
let _ = || {
|
||||
let Foo { .. } = foo.as_ref();
|
||||
let Foo { x, y } = foo.as_ref();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(y);
|
||||
let Pin { .. } = foo.as_ref();
|
||||
};
|
||||
}
|
||||
|
||||
fn bar_mut<T: Unpin, U: Unpin>(mut bar: Pin<&mut Bar<T, U>>) {
|
||||
let Bar(..) = bar.as_mut();
|
||||
let Bar(x, y) = bar.as_mut();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(y);
|
||||
let Pin { .. } = bar.as_mut();
|
||||
|
||||
let _ = || {
|
||||
let Bar(..) = bar.as_mut();
|
||||
let Bar(x, y) = bar.as_mut();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_mut(y);
|
||||
let Pin { .. } = bar.as_mut();
|
||||
};
|
||||
}
|
||||
|
||||
fn bar_const<T: Unpin, U: Unpin>(bar: Pin<&Bar<T, U>>) {
|
||||
let Bar(..) = bar.as_ref();
|
||||
let Bar(x, y) = bar.as_ref();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(y);
|
||||
let Pin { .. } = bar.as_ref();
|
||||
|
||||
let _ = || {
|
||||
let Bar(..) = bar.as_ref();
|
||||
let Bar(x, y) = bar.as_ref();
|
||||
//[normal]~^ ERROR cannot move out of a shared reference
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(x);
|
||||
#[cfg(pin_ergonomics)]
|
||||
assert_pin_const(y);
|
||||
let Pin { .. } = bar.as_ref();
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:121:9
|
||||
|
|
||||
LL | let NonPinProject { x } = foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:125:9
|
||||
|
|
||||
LL | let NonPinProject { x } = bar;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:131:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:139:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:37:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:45:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:59:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:67:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:81:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:89:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:103:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:111:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:37:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:45:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:59:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:67:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:81:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:89:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:103:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:111:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:131:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut NonPinProject<T>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut NonPinProject<T>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:139:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&NonPinProject<U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&NonPinProject<U>>`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:33:9
|
||||
|
|
||||
LL | let Foo { x, y } = foo.as_mut();
|
||||
| ^^^^^^^^^^^^ ------------ this expression has type `Pin<&mut Foo<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&mut Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Foo { x, y } = *foo.as_mut();
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:37:9
|
||||
|
|
||||
LL | match foo.as_mut() {
|
||||
| ------------ this expression has type `Pin<&mut Foo<T, U>>`
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ expected `Pin<&mut Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *foo.as_mut() {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:45:9
|
||||
|
|
||||
LL | let _ = || match foo.as_mut() {
|
||||
| ------------ this expression has type `Pin<&mut Foo<T, U>>`
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ expected `Pin<&mut Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let _ = || match *foo.as_mut() {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:55:9
|
||||
|
|
||||
LL | let Foo { x, y } = foo;
|
||||
| ^^^^^^^^^^^^ --- this expression has type `Pin<&Foo<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Foo { x, y } = *foo;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:59:9
|
||||
|
|
||||
LL | match foo {
|
||||
| --- this expression has type `Pin<&Foo<T, U>>`
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ expected `Pin<&Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *foo {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:67:9
|
||||
|
|
||||
LL | let _ = || match foo {
|
||||
| --- this expression has type `Pin<&Foo<T, U>>`
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ expected `Pin<&Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let _ = || match *foo {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:77:9
|
||||
|
|
||||
LL | let Bar(x, y) = bar.as_mut();
|
||||
| ^^^^^^^^^ ------------ this expression has type `Pin<&mut Bar<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&mut Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Bar(x, y) = *bar.as_mut();
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:81:9
|
||||
|
|
||||
LL | match bar.as_mut() {
|
||||
| ------------ this expression has type `Pin<&mut Bar<T, U>>`
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ expected `Pin<&mut Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *bar.as_mut() {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:89:9
|
||||
|
|
||||
LL | let _ = || match bar.as_mut() {
|
||||
| ------------ this expression has type `Pin<&mut Bar<T, U>>`
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ expected `Pin<&mut Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let _ = || match *bar.as_mut() {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:99:9
|
||||
|
|
||||
LL | let Bar(x, y) = bar;
|
||||
| ^^^^^^^^^ --- this expression has type `Pin<&Bar<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Bar(x, y) = *bar;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:103:9
|
||||
|
|
||||
LL | match bar {
|
||||
| --- this expression has type `Pin<&Bar<T, U>>`
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ expected `Pin<&Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *bar {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:111:9
|
||||
|
|
||||
LL | let _ = || match bar {
|
||||
| --- this expression has type `Pin<&Bar<T, U>>`
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ expected `Pin<&Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Bar<T, U>>`
|
||||
found struct `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let _ = || match *bar {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:121:9
|
||||
|
|
||||
LL | let NonPinProject { x } = foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^ --- this expression has type `Pin<&mut NonPinProject<T>>`
|
||||
| |
|
||||
| expected `Pin<&mut NonPinProject<T>>`, found `NonPinProject<_>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut NonPinProject<T>>`
|
||||
found struct `NonPinProject<_>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let NonPinProject { x } = *foo;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:125:9
|
||||
|
|
||||
LL | let NonPinProject { x } = bar;
|
||||
| ^^^^^^^^^^^^^^^^^^^ --- this expression has type `Pin<&NonPinProject<U>>`
|
||||
| |
|
||||
| expected `Pin<&NonPinProject<U>>`, found `NonPinProject<_>`
|
||||
|
|
||||
= note: expected struct `Pin<&NonPinProject<U>>`
|
||||
found struct `NonPinProject<_>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let NonPinProject { x } = *bar;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:131:9
|
||||
|
|
||||
LL | match foo {
|
||||
| --- this expression has type `Pin<&mut NonPinProject<T>>`
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `Pin<&mut NonPinProject<T>>`, found `NonPinProject<_>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut NonPinProject<T>>`
|
||||
found struct `NonPinProject<_>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *foo {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:139:9
|
||||
|
|
||||
LL | match bar {
|
||||
| --- this expression has type `Pin<&NonPinProject<U>>`
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `Pin<&NonPinProject<U>>`, found `NonPinProject<_>`
|
||||
|
|
||||
= note: expected struct `Pin<&NonPinProject<U>>`
|
||||
found struct `NonPinProject<_>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *bar {
|
||||
| +
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:121:9
|
||||
|
|
||||
LL | let NonPinProject { x } = foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:125:9
|
||||
|
|
||||
LL | let NonPinProject { x } = bar;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:131:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: cannot project on type that is not `#[pin_v2]`
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:139:9
|
||||
|
|
||||
LL | NonPinProject { x } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type defined here
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:28:1
|
||||
|
|
||||
LL | struct NonPinProject<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add `#[pin_v2]` here
|
||||
|
|
||||
LL + #[pin_v2]
|
||||
LL | struct NonPinProject<T> {
|
||||
|
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:37:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:45:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:59:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:67:9
|
||||
|
|
||||
LL | Foo { x, y } => {}
|
||||
| ^^^^^^^^^^^^ matches on the result of dereferencing `Pin<&Foo<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Foo<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:81:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:89:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&mut Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&mut Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:103:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: mix of deref patterns and normal constructors
|
||||
--> $DIR/pattern-matching-mix-deref-pattern.rs:111:9
|
||||
|
|
||||
LL | Bar(x, y) => {}
|
||||
| ^^^^^^^^^ matches on the result of dereferencing `Pin<&Bar<T, U>>`
|
||||
...
|
||||
LL | Pin { .. } => {}
|
||||
| ^^^^^^^^^^ matches directly on `Pin<&Bar<T, U>>`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
148
tests/ui/pin-ergonomics/pattern-matching-mix-deref-pattern.rs
Normal file
148
tests/ui/pin-ergonomics/pattern-matching-mix-deref-pattern.rs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//@ revisions: normal pin_ergonomics deref_patterns both
|
||||
//@ edition:2024
|
||||
#![cfg_attr(any(pin_ergonomics, both), feature(pin_ergonomics))]
|
||||
#![cfg_attr(any(deref_patterns, both), feature(deref_patterns))]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// This test verifies that the `pin_ergonomics` feature works well
|
||||
// together with the `deref_patterns` feature under the error:
|
||||
// "mix of deref patterns and normal constructors".
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
#[cfg_attr(any(pin_ergonomics, both), pin_v2)]
|
||||
struct Foo<T, U> {
|
||||
x: T,
|
||||
y: U,
|
||||
}
|
||||
|
||||
#[cfg_attr(any(pin_ergonomics, both), pin_v2)]
|
||||
struct Bar<T, U>(T, U);
|
||||
|
||||
#[cfg_attr(any(pin_ergonomics, both), pin_v2)]
|
||||
enum Baz<T, U> {
|
||||
Foo(T, U),
|
||||
Bar { x: T, y: U },
|
||||
}
|
||||
|
||||
struct NonPinProject<T> {
|
||||
x: T,
|
||||
}
|
||||
|
||||
fn foo_mut<T: Unpin, U: Unpin>(mut foo: Pin<&mut Foo<T, U>>) {
|
||||
let Foo { x, y } = foo.as_mut();
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|
||||
match foo.as_mut() {
|
||||
Foo { x, y } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
}
|
||||
let _ = || match foo.as_mut() {
|
||||
Foo { x, y } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn foo_const<T: Unpin, U: Unpin>(foo: Pin<&Foo<T, U>>) {
|
||||
let Foo { x, y } = foo;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|
||||
match foo {
|
||||
Foo { x, y } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
}
|
||||
let _ = || match foo {
|
||||
Foo { x, y } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn bar_mut<T: Unpin, U: Unpin>(bar: Pin<&mut Bar<T, U>>) {
|
||||
let Bar(x, y) = bar.as_mut();
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|
||||
match bar.as_mut() {
|
||||
Bar(x, y) => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
}
|
||||
let _ = || match bar.as_mut() {
|
||||
Bar(x, y) => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn bar_const<T: Unpin, U: Unpin>(bar: Pin<&Bar<T, U>>) {
|
||||
let Bar(x, y) = bar;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
|
||||
match bar {
|
||||
Bar(x, y) => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
}
|
||||
let _ = || match bar {
|
||||
Bar(x, y) => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR mix of deref patterns and normal constructors
|
||||
//[both]~^^^^ ERROR mix of deref patterns and normal constructors
|
||||
Pin { .. } => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn non_pin_project<T, U: Unpin>(foo: Pin<&mut NonPinProject<T>>, bar: Pin<&NonPinProject<U>>) {
|
||||
let NonPinProject { x } = foo;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
//[both]~^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
let NonPinProject { x } = bar;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[pin_ergonomics]~^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
//[both]~^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
|
||||
match foo {
|
||||
NonPinProject { x } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
//[both]~^^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
Pin { .. } => {}
|
||||
}
|
||||
match bar {
|
||||
NonPinProject { x } => {}
|
||||
//[normal]~^ ERROR mismatched types
|
||||
//[deref_patterns]~^^ ERROR mix of deref patterns and normal constructors
|
||||
//[pin_ergonomics]~^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
//[both]~^^^^ ERROR cannot project on type that is not `#[pin_v2]`
|
||||
Pin { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
242
tests/ui/pin-ergonomics/pattern-matching.normal.stderr
Normal file
242
tests/ui/pin-ergonomics/pattern-matching.normal.stderr
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
error[E0658]: the `#[pin_v2]` attribute is an experimental feature
|
||||
--> $DIR/pattern-matching.rs:12:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
|
||||
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[pin_v2]` attribute is an experimental feature
|
||||
--> $DIR/pattern-matching.rs:18:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
|
||||
= help: add `#![feature(pin_ergonomics)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:33:9
|
||||
|
|
||||
LL | let Foo { x, y } = foo_mut;
|
||||
| ^^^^^^^^^^^^ ------- this expression has type `Pin<&mut Foo<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&mut Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Foo { x, y } = *foo_mut;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:38:9
|
||||
|
|
||||
LL | let Foo { x, y } = foo_const;
|
||||
| ^^^^^^^^^^^^ --------- this expression has type `Pin<&Foo<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&Foo<T, U>>`, found `Foo<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Foo<T, U>>`
|
||||
found struct `Foo<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let Foo { x, y } = *foo_const;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:46:9
|
||||
|
|
||||
LL | match bar_mut {
|
||||
| ------- this expression has type `Pin<&mut Bar<T, U>>`
|
||||
LL | Bar::Foo(x, y) => {
|
||||
| ^^^^^^^^^^^^^^ expected `Pin<&mut Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Bar<T, U>>`
|
||||
found enum `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *bar_mut {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:51:18
|
||||
|
|
||||
LL | _ if let Bar::Bar { x, y } = bar_mut => {
|
||||
| ^^^^^^^^^^^^^^^^^ ------- this expression has type `Pin<&mut Bar<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&mut Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&mut Bar<T, U>>`
|
||||
found enum `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | _ if let Bar::Bar { x, y } = *bar_mut => {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:59:9
|
||||
|
|
||||
LL | match bar_const {
|
||||
| --------- this expression has type `Pin<&Bar<T, U>>`
|
||||
LL | Bar::Bar { x, y } => {
|
||||
| ^^^^^^^^^^^^^^^^^ expected `Pin<&Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Bar<T, U>>`
|
||||
found enum `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | match *bar_const {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:64:18
|
||||
|
|
||||
LL | _ if let Bar::Foo(x, y) = bar_const => {
|
||||
| ^^^^^^^^^^^^^^ --------- this expression has type `Pin<&Bar<T, U>>`
|
||||
| |
|
||||
| expected `Pin<&Bar<T, U>>`, found `Bar<_, _>`
|
||||
|
|
||||
= note: expected struct `Pin<&Bar<T, U>>`
|
||||
found enum `Bar<_, _>`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | _ if let Bar::Foo(x, y) = *bar_const => {
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:74:9
|
||||
|
|
||||
LL | let (Foo { x, y },) = foo_mut;
|
||||
| ^^^^^^^^^^^^^^^ ------- this expression has type `Pin<&mut (Foo<T, U>,)>`
|
||||
| |
|
||||
| expected `Pin<&mut (Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&mut (Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let (Foo { x, y },) = *foo_mut;
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:78:9
|
||||
|
|
||||
LL | let (Foo { x, y },) = foo_const;
|
||||
| ^^^^^^^^^^^^^^^ --------- this expression has type `Pin<&(Foo<T, U>,)>`
|
||||
| |
|
||||
| expected `Pin<&(Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&(Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
help: consider dereferencing to access the inner value using the Deref trait
|
||||
|
|
||||
LL | let (Foo { x, y },) = *foo_const;
|
||||
| +
|
||||
|
||||
error[E0529]: expected an array or slice, found `Pin<&mut [Foo<T, U>; 1]>`
|
||||
--> $DIR/pattern-matching.rs:85:9
|
||||
|
|
||||
LL | let [Foo { x, y }] = foo_mut;
|
||||
| ^^^^^^^^^^^^^^ pattern cannot match with input type `Pin<&mut [Foo<T, U>; 1]>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `Pin<&[Foo<T, U>; 1]>`
|
||||
--> $DIR/pattern-matching.rs:89:9
|
||||
|
|
||||
LL | let [Foo { x, y }] = foo_const;
|
||||
| ^^^^^^^^^^^^^^ pattern cannot match with input type `Pin<&[Foo<T, U>; 1]>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `Pin<&mut [Foo<T, U>]>`
|
||||
--> $DIR/pattern-matching.rs:96:12
|
||||
|
|
||||
LL | if let [Foo { x, y }] = foo_mut {
|
||||
| ^^^^^^^^^^^^^^ pattern cannot match with input type `Pin<&mut [Foo<T, U>]>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `Pin<&[Foo<T, U>]>`
|
||||
--> $DIR/pattern-matching.rs:101:12
|
||||
|
|
||||
LL | if let [Foo { x, y }] = foo_const {
|
||||
| ^^^^^^^^^^^^^^ pattern cannot match with input type `Pin<&[Foo<T, U>]>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:109:5
|
||||
|
|
||||
LL | (&mut x,): Pin<&'a mut (&'a mut Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut (&mut Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut (&'a mut Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:115:5
|
||||
|
|
||||
LL | (&mut x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut &mut (Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut &'a mut (Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:121:5
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut (&mut Foo<T, U>,)>`, found `&mut _`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut (&'a mut Foo<T, U>,)>`
|
||||
found mutable reference `&mut _`
|
||||
help: you might have meant to use field `pointer` whose type is `&'a mut (&'a mut Foo<T, U>,)`
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>.pointer,
|
||||
| ++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:127:5
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut &mut (Foo<T, U>,)>`, found `&mut _`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut &'a mut (Foo<T, U>,)>`
|
||||
found mutable reference `&mut _`
|
||||
help: you might have meant to use field `pointer` whose type is `&'a mut &'a mut (Foo<T, U>,)`
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>.pointer,
|
||||
| ++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:133:5
|
||||
|
|
||||
LL | (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>,
|
||||
| ^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut (&mut Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut (&'a mut Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:139:5
|
||||
|
|
||||
LL | (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut &mut (Foo<T, U>,)>`, found `(_,)`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut &'a mut (Foo<T, U>,)>`
|
||||
found tuple `(_,)`
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0529, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:115:6
|
||||
|
|
||||
LL | (&mut x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Foo<T, U>`, found `&mut _`
|
||||
|
|
||||
= note: expected struct `Foo<T, U>`
|
||||
found mutable reference `&mut _`
|
||||
note: to declare a mutable binding use: `mut x`
|
||||
--> $DIR/pattern-matching.rs:115:6
|
||||
|
|
||||
LL | (&mut x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^^^
|
||||
help: consider removing `&mut` from the pattern
|
||||
|
|
||||
LL - (&mut x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
LL + (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:121:5
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut (&mut Foo<T, U>,)>`, found `&mut _`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut (&'a mut Foo<T, U>,)>`
|
||||
found mutable reference `&mut _`
|
||||
help: you might have meant to use field `pointer` whose type is `&'a mut (&'a mut Foo<T, U>,)`
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>.pointer,
|
||||
| ++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pattern-matching.rs:127:5
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>,
|
||||
| ^^^^^^^^^ --------------------------------- expected due to this
|
||||
| |
|
||||
| expected `Pin<&mut &mut (Foo<T, U>,)>`, found `&mut _`
|
||||
|
|
||||
= note: expected struct `Pin<&'a mut &'a mut (Foo<T, U>,)>`
|
||||
found mutable reference `&mut _`
|
||||
help: you might have meant to use field `pointer` whose type is `&'a mut &'a mut (Foo<T, U>,)`
|
||||
|
|
||||
LL | &mut (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>.pointer,
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
144
tests/ui/pin-ergonomics/pattern-matching.rs
Normal file
144
tests/ui/pin-ergonomics/pattern-matching.rs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
//@ revisions: pin_ergonomics normal
|
||||
//@ edition:2024
|
||||
#![cfg_attr(pin_ergonomics, feature(pin_ergonomics))]
|
||||
#![feature(if_let_guard, negative_impls)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
// This test verifies that a `&pin mut T` can be projected to a pinned
|
||||
// reference field `&pin mut T.U` when `T` is marked with `#[pin_v2]`.
|
||||
|
||||
#[pin_v2] //[normal]~ ERROR the `#[pin_v2]` attribute is an experimental feature
|
||||
struct Foo<T, U> {
|
||||
x: T,
|
||||
y: U,
|
||||
}
|
||||
|
||||
#[pin_v2] //[normal]~ ERROR the `#[pin_v2]` attribute is an experimental feature
|
||||
enum Bar<T, U> {
|
||||
Foo(T, U),
|
||||
Bar { x: T, y: U },
|
||||
}
|
||||
|
||||
trait IsPinMut {}
|
||||
trait IsPinConst {}
|
||||
impl<T: ?Sized> IsPinMut for Pin<&mut T> {}
|
||||
impl<T: ?Sized> IsPinConst for Pin<&T> {}
|
||||
|
||||
fn assert_pin_mut<T: IsPinMut>(_: T) {}
|
||||
fn assert_pin_const<T: IsPinConst>(_: T) {}
|
||||
|
||||
fn foo<T: Unpin, U: Unpin>(foo_mut: Pin<&mut Foo<T, U>>, foo_const: Pin<&Foo<T, U>>) {
|
||||
let Foo { x, y } = foo_mut;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
|
||||
let Foo { x, y } = foo_const;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
|
||||
fn bar<T: Unpin, U: Unpin>(bar_mut: Pin<&mut Bar<T, U>>, bar_const: Pin<&Bar<T, U>>) {
|
||||
match bar_mut {
|
||||
Bar::Foo(x, y) => {
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
}
|
||||
_ if let Bar::Bar { x, y } = bar_mut => {
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match bar_const {
|
||||
Bar::Bar { x, y } => {
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
_ if let Bar::Foo(x, y) = bar_const => {
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn pin_mut_tuple<T, U>(foo_mut: Pin<&mut (Foo<T, U>,)>, foo_const: Pin<&(Foo<T, U>,)>) {
|
||||
let (Foo { x, y },) = foo_mut;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
let (Foo { x, y },) = foo_const;
|
||||
//[normal]~^ ERROR mismatched types
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
|
||||
fn pin_mut_array<T, U>(foo_mut: Pin<&mut [Foo<T, U>; 1]>, foo_const: Pin<&[Foo<T, U>; 1]>) {
|
||||
let [Foo { x, y }] = foo_mut;
|
||||
//[normal]~^ ERROR expected an array or slice, found `Pin<&mut [Foo<T, U>; 1]>`
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
let [Foo { x, y }] = foo_const;
|
||||
//[normal]~^ ERROR expected an array or slice, found `Pin<&[Foo<T, U>; 1]>`
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
|
||||
fn pin_mut_slice<T, U>(foo_mut: Pin<&mut [Foo<T, U>]>, foo_const: Pin<&[Foo<T, U>]>) {
|
||||
if let [Foo { x, y }] = foo_mut {
|
||||
//[normal]~^ ERROR expected an array or slice, found `Pin<&mut [Foo<T, U>]>`
|
||||
assert_pin_mut(x);
|
||||
assert_pin_mut(y);
|
||||
}
|
||||
if let [Foo { x, y }] = foo_const {
|
||||
//[normal]~^ ERROR expected an array or slice, found `Pin<&[Foo<T, U>]>`
|
||||
assert_pin_const(x);
|
||||
assert_pin_const(y);
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_ref_mut_pat_and_pin_mut_of_tuple_mut_ty<'a, T, U>(
|
||||
(&mut x,): Pin<&'a mut (&'a mut Foo<T, U>,)>, //[normal]~ ERROR mismatched type
|
||||
) -> Pin<&'a mut Foo<T, U>> {
|
||||
x
|
||||
}
|
||||
|
||||
fn tuple_ref_mut_pat_and_pin_mut_of_mut_tuple_ty<'a, T, U>(
|
||||
(&mut x,): Pin<&'a mut &'a mut (Foo<T, U>,)>, //~ ERROR mismatched type
|
||||
) -> Pin<&'a mut Foo<T, U>> {
|
||||
x
|
||||
}
|
||||
|
||||
fn ref_mut_tuple_pat_and_pin_mut_of_tuple_mut_ty<'a, T, U>(
|
||||
&mut (x,): Pin<&'a mut (&'a mut Foo<T, U>,)>, //~ ERROR mismatched type
|
||||
) -> Pin<&'a mut Foo<T, U>> {
|
||||
x
|
||||
}
|
||||
|
||||
fn ref_mut_tuple_pat_and_pin_mut_of_mut_tuple_ty<'a, T, U>(
|
||||
&mut (x,): Pin<&'a mut &'a mut (Foo<T, U>,)>, //~ ERROR mismatched type
|
||||
) -> Pin<&'a mut Foo<T, U>> {
|
||||
x
|
||||
}
|
||||
|
||||
fn tuple_pat_and_pin_mut_of_tuple_mut_ty<'a, T, U>(
|
||||
(x,): Pin<&'a mut (&'a mut Foo<T, U>,)>, //[normal]~ ERROR mismatched type
|
||||
) -> Pin<&'a mut &'a mut Foo<T, U>> {
|
||||
x // ok
|
||||
}
|
||||
|
||||
fn tuple_pat_and_pin_mut_of_mut_tuple_ty<'a, T, U>(
|
||||
(x,): Pin<&'a mut &'a mut (Foo<T, U>,)>, //[normal]~ ERROR mismatched type
|
||||
) -> Pin<&'a mut Foo<T, U>> {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
138
tests/ui/pin-ergonomics/pin_v2-attr.rs
Normal file
138
tests/ui/pin-ergonomics/pin_v2-attr.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#![feature(
|
||||
pin_ergonomics,
|
||||
where_clause_attrs,
|
||||
trait_alias,
|
||||
extern_types,
|
||||
associated_type_defaults,
|
||||
fn_delegation,
|
||||
)]
|
||||
#![allow(incomplete_features)]
|
||||
#![pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on crates
|
||||
|
||||
// allowed
|
||||
|
||||
#[pin_v2]
|
||||
struct Struct {}
|
||||
|
||||
#[pin_v2]
|
||||
enum Enum {}
|
||||
|
||||
#[pin_v2]
|
||||
union Union {
|
||||
field: (),
|
||||
}
|
||||
|
||||
// disallowed
|
||||
|
||||
enum Foo<#[pin_v2] T, #[pin_v2] U = ()> {
|
||||
//~^ ERROR `#[pin_v2]` attribute cannot be used on function params
|
||||
//~| ERROR `#[pin_v2]` attribute cannot be used on function params
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on enum variants
|
||||
UnitVariant,
|
||||
TupleVariant(#[pin_v2] T), //~ ERROR `#[pin_v2]` attribute cannot be used on struct fields
|
||||
StructVariant {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on struct fields
|
||||
field: U,
|
||||
},
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on traits
|
||||
trait Trait {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on associated consts
|
||||
const ASSOC_CONST: () = ();
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on associated types
|
||||
type AssocType = ();
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on required trait methods
|
||||
fn method();
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on provided trait methods
|
||||
fn method_with_body() {}
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on trait aliases
|
||||
trait TraitAlias = Trait;
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on inherent impl blocks
|
||||
impl Struct {
|
||||
// FIXME: delegation macros are not tested yet (how to?)
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on delegations
|
||||
reuse <Struct as std::any::Any>::type_id;
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on inherent methods
|
||||
fn method() {}
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on trait impl blocks
|
||||
impl Trait for Enum {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on trait methods in impl blocks
|
||||
fn method() {}
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on extern crates
|
||||
extern crate alloc;
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on use statements
|
||||
use std::pin::Pin;
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on statics
|
||||
static STATIC: () = ();
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on constants
|
||||
const CONST: () = ();
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on functions
|
||||
fn f<T, U>(#[pin_v2] param: Foo<T, U>)
|
||||
//~^ ERROR `#[pin_v2]` attribute cannot be used on function params
|
||||
//~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
where
|
||||
#[pin_v2]
|
||||
//~^ ERROR `#[pin_v2]` attribute cannot be used on where predicates
|
||||
T:,
|
||||
{
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on closures
|
||||
|| ();
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on expressions
|
||||
[(), (), ()];
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on statements
|
||||
let _: Foo<(), ()> = Foo::StructVariant {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on struct fields
|
||||
field: (),
|
||||
};
|
||||
match param {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on match arms
|
||||
Foo::UnitVariant => {}
|
||||
Foo::TupleVariant(..) => {}
|
||||
Foo::StructVariant {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on pattern fields
|
||||
field,
|
||||
} => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on modules
|
||||
mod m {}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on foreign modules
|
||||
extern "C" {
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on foreign types
|
||||
type ForeignTy;
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on foreign statics
|
||||
static EXTERN_STATIC: ();
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on foreign functions
|
||||
fn extern_fn();
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on type alias
|
||||
type Type = ();
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on macro defs
|
||||
macro_rules! macro_def {
|
||||
() => {};
|
||||
}
|
||||
|
||||
#[pin_v2] //~ ERROR `#[pin_v2]` attribute cannot be used on macro calls
|
||||
macro_def!();
|
||||
|
||||
fn main() {}
|
||||
312
tests/ui/pin-ergonomics/pin_v2-attr.stderr
Normal file
312
tests/ui/pin-ergonomics/pin_v2-attr.stderr
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
error: `#[pin_v2]` attribute cannot be used on macro calls
|
||||
--> $DIR/pin_v2-attr.rs:135:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/pin_v2-attr.rs:84:12
|
||||
|
|
||||
LL | fn f<T, U>(#[pin_v2] param: Foo<T, U>)
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on crates
|
||||
--> $DIR/pin_v2-attr.rs:10:1
|
||||
|
|
||||
LL | #![pin_v2]
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on function params
|
||||
--> $DIR/pin_v2-attr.rs:27:10
|
||||
|
|
||||
LL | enum Foo<#[pin_v2] T, #[pin_v2] U = ()> {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on function params
|
||||
--> $DIR/pin_v2-attr.rs:27:23
|
||||
|
|
||||
LL | enum Foo<#[pin_v2] T, #[pin_v2] U = ()> {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on enum variants
|
||||
--> $DIR/pin_v2-attr.rs:30:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on struct fields
|
||||
--> $DIR/pin_v2-attr.rs:32:18
|
||||
|
|
||||
LL | TupleVariant(#[pin_v2] T),
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on struct fields
|
||||
--> $DIR/pin_v2-attr.rs:34:9
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on traits
|
||||
--> $DIR/pin_v2-attr.rs:39:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on associated consts
|
||||
--> $DIR/pin_v2-attr.rs:41:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on associated types
|
||||
--> $DIR/pin_v2-attr.rs:43:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on required trait methods
|
||||
--> $DIR/pin_v2-attr.rs:46:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on provided trait methods
|
||||
--> $DIR/pin_v2-attr.rs:48:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on trait aliases
|
||||
--> $DIR/pin_v2-attr.rs:52:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on inherent impl blocks
|
||||
--> $DIR/pin_v2-attr.rs:55:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on delegations
|
||||
--> $DIR/pin_v2-attr.rs:58:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on inherent methods
|
||||
--> $DIR/pin_v2-attr.rs:61:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on trait impl blocks
|
||||
--> $DIR/pin_v2-attr.rs:65:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on trait methods in impl blocks
|
||||
--> $DIR/pin_v2-attr.rs:67:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on extern crates
|
||||
--> $DIR/pin_v2-attr.rs:71:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on use statements
|
||||
--> $DIR/pin_v2-attr.rs:74:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on statics
|
||||
--> $DIR/pin_v2-attr.rs:77:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on constants
|
||||
--> $DIR/pin_v2-attr.rs:80:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on functions
|
||||
--> $DIR/pin_v2-attr.rs:83:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on function params
|
||||
--> $DIR/pin_v2-attr.rs:84:12
|
||||
|
|
||||
LL | fn f<T, U>(#[pin_v2] param: Foo<T, U>)
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on closures
|
||||
--> $DIR/pin_v2-attr.rs:92:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on expressions
|
||||
--> $DIR/pin_v2-attr.rs:94:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on struct fields
|
||||
--> $DIR/pin_v2-attr.rs:98:9
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on statements
|
||||
--> $DIR/pin_v2-attr.rs:96:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on match arms
|
||||
--> $DIR/pin_v2-attr.rs:102:9
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on pattern fields
|
||||
--> $DIR/pin_v2-attr.rs:106:13
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on where predicates
|
||||
--> $DIR/pin_v2-attr.rs:88:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on modules
|
||||
--> $DIR/pin_v2-attr.rs:112:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on foreign modules
|
||||
--> $DIR/pin_v2-attr.rs:115:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on foreign types
|
||||
--> $DIR/pin_v2-attr.rs:117:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on foreign statics
|
||||
--> $DIR/pin_v2-attr.rs:120:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on foreign functions
|
||||
--> $DIR/pin_v2-attr.rs:123:5
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on type aliases
|
||||
--> $DIR/pin_v2-attr.rs:127:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: `#[pin_v2]` attribute cannot be used on macro defs
|
||||
--> $DIR/pin_v2-attr.rs:130:1
|
||||
|
|
||||
LL | #[pin_v2]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: `#[pin_v2]` can be applied to data types and unions
|
||||
|
||||
error: aborting due to 39 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue