mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 14:23:45 +00:00
Add sugar for &pin (const|mut) types
This commit is contained in:
parent
7caad69253
commit
ae698f8199
@ -23,7 +23,7 @@ use std::{cmp, fmt, mem};
|
|||||||
|
|
||||||
pub use GenericArgs::*;
|
pub use GenericArgs::*;
|
||||||
pub use UnsafeSource::*;
|
pub use UnsafeSource::*;
|
||||||
pub use rustc_ast_ir::{Movability, Mutability};
|
pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
|
||||||
use rustc_data_structures::packed::Pu128;
|
use rustc_data_structures::packed::Pu128;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
@ -2161,6 +2161,10 @@ pub enum TyKind {
|
|||||||
Ptr(MutTy),
|
Ptr(MutTy),
|
||||||
/// A reference (`&'a T` or `&'a mut T`).
|
/// A reference (`&'a T` or `&'a mut T`).
|
||||||
Ref(Option<Lifetime>, MutTy),
|
Ref(Option<Lifetime>, MutTy),
|
||||||
|
/// A pinned reference (`&'a pin const T` or `&'a pin mut T`).
|
||||||
|
///
|
||||||
|
/// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`.
|
||||||
|
PinnedRef(Option<Lifetime>, MutTy),
|
||||||
/// A bare function (e.g., `fn(usize) -> bool`).
|
/// A bare function (e.g., `fn(usize) -> bool`).
|
||||||
BareFn(P<BareFnTy>),
|
BareFn(P<BareFnTy>),
|
||||||
/// The never type (`!`).
|
/// The never type (`!`).
|
||||||
@ -2509,7 +2513,10 @@ impl Param {
|
|||||||
if ident.name == kw::SelfLower {
|
if ident.name == kw::SelfLower {
|
||||||
return match self.ty.kind {
|
return match self.ty.kind {
|
||||||
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||||
TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => {
|
TyKind::Ref(lt, MutTy { ref ty, mutbl })
|
||||||
|
| TyKind::PinnedRef(lt, MutTy { ref ty, mutbl })
|
||||||
|
if ty.kind.is_implicit_self() =>
|
||||||
|
{
|
||||||
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
Some(respan(self.pat.span, SelfKind::Region(lt, mutbl)))
|
||||||
}
|
}
|
||||||
_ => Some(respan(
|
_ => Some(respan(
|
||||||
|
@ -485,7 +485,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
|
|||||||
}
|
}
|
||||||
TyKind::Slice(ty) => vis.visit_ty(ty),
|
TyKind::Slice(ty) => vis.visit_ty(ty),
|
||||||
TyKind::Ptr(mt) => vis.visit_mt(mt),
|
TyKind::Ptr(mt) => vis.visit_mt(mt),
|
||||||
TyKind::Ref(lt, mt) => {
|
TyKind::Ref(lt, mt) | TyKind::PinnedRef(lt, mt) => {
|
||||||
visit_opt(lt, |lt| vis.visit_lifetime(lt));
|
visit_opt(lt, |lt| vis.visit_lifetime(lt));
|
||||||
vis.visit_mt(mt);
|
vis.visit_mt(mt);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,9 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
|
|||||||
break (mac.args.delim == Delimiter::Brace).then_some(mac);
|
break (mac.args.delim == Delimiter::Brace).then_some(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
|
ast::TyKind::Ptr(mut_ty)
|
||||||
|
| ast::TyKind::Ref(_, mut_ty)
|
||||||
|
| ast::TyKind::PinnedRef(_, mut_ty) => {
|
||||||
ty = &mut_ty.ty;
|
ty = &mut_ty.ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +499,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
|||||||
match kind {
|
match kind {
|
||||||
TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
|
TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
|
||||||
TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
|
TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
|
||||||
TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) => {
|
TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
|
||||||
|
| TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
|
||||||
visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
|
visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
}
|
}
|
||||||
|
@ -79,3 +79,10 @@ impl Mutability {
|
|||||||
matches!(self, Self::Not)
|
matches!(self, Self::Not)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
|
||||||
|
pub enum Pinnedness {
|
||||||
|
Not,
|
||||||
|
Pinned,
|
||||||
|
}
|
||||||
|
@ -640,7 +640,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.lower_span(span),
|
self.lower_span(span),
|
||||||
Some(self.allow_gen_future.clone()),
|
Some(self.allow_gen_future.clone()),
|
||||||
);
|
);
|
||||||
let resume_ty = self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span);
|
let resume_ty =
|
||||||
|
self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);
|
||||||
let input_ty = hir::Ty {
|
let input_ty = hir::Ty {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
kind: hir::TyKind::Path(resume_ty),
|
kind: hir::TyKind::Path(resume_ty),
|
||||||
@ -2065,7 +2066,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
lang_item: hir::LangItem,
|
lang_item: hir::LangItem,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span));
|
let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None);
|
||||||
let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
|
let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
|
||||||
self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
|
self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
|
||||||
self.arena.alloc(hir::PathSegment::new(
|
self.arena.alloc(hir::PathSegment::new(
|
||||||
|
@ -55,8 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
|
|||||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
|
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName,
|
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind,
|
||||||
TraitCandidate,
|
ParamName, TraitCandidate,
|
||||||
};
|
};
|
||||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
@ -765,8 +765,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> {
|
fn make_lang_item_qpath(
|
||||||
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, None))
|
&mut self,
|
||||||
|
lang_item: hir::LangItem,
|
||||||
|
span: Span,
|
||||||
|
args: Option<&'hir hir::GenericArgs<'hir>>,
|
||||||
|
) -> hir::QPath<'hir> {
|
||||||
|
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_lang_item_path(
|
fn make_lang_item_path(
|
||||||
@ -1317,6 +1322,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let lifetime = self.lower_lifetime(®ion);
|
let lifetime = self.lower_lifetime(®ion);
|
||||||
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
|
hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
|
||||||
}
|
}
|
||||||
|
TyKind::PinnedRef(region, mt) => {
|
||||||
|
let region = region.unwrap_or_else(|| {
|
||||||
|
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
|
||||||
|
self.resolver.get_lifetime_res(t.id)
|
||||||
|
{
|
||||||
|
debug_assert_eq!(start.plus(1), end);
|
||||||
|
start
|
||||||
|
} else {
|
||||||
|
self.next_node_id()
|
||||||
|
};
|
||||||
|
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
|
||||||
|
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
|
||||||
|
});
|
||||||
|
let lifetime = self.lower_lifetime(®ion);
|
||||||
|
let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
|
||||||
|
let span = self.lower_span(t.span);
|
||||||
|
let arg = hir::Ty { kind, span, hir_id: self.next_id() };
|
||||||
|
let args = self.arena.alloc(hir::GenericArgs {
|
||||||
|
args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]),
|
||||||
|
constraints: &[],
|
||||||
|
parenthesized: hir::GenericArgsParentheses::No,
|
||||||
|
span_ext: span,
|
||||||
|
});
|
||||||
|
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
|
||||||
|
hir::TyKind::Path(path)
|
||||||
|
}
|
||||||
TyKind::BareFn(f) => {
|
TyKind::BareFn(f) => {
|
||||||
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
|
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
|
||||||
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
|
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
|
||||||
@ -1882,10 +1913,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// Given we are only considering `ImplicitSelf` types, we needn't consider
|
// Given we are only considering `ImplicitSelf` types, we needn't consider
|
||||||
// the case where we have a mutable pattern to a reference as that would
|
// the case where we have a mutable pattern to a reference as that would
|
||||||
// no longer be an `ImplicitSelf`.
|
// no longer be an `ImplicitSelf`.
|
||||||
TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl {
|
TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt)
|
||||||
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
|
if mt.ty.kind.is_implicit_self() =>
|
||||||
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
|
{
|
||||||
},
|
match mt.mutbl {
|
||||||
|
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
|
||||||
|
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => hir::ImplicitSelfKind::None,
|
_ => hir::ImplicitSelfKind::None,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -95,7 +95,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
|
|||||||
visit::walk_ty(self, t);
|
visit::walk_ty(self, t);
|
||||||
self.current_binders.pop();
|
self.current_binders.pop();
|
||||||
}
|
}
|
||||||
TyKind::Ref(None, _) => {
|
TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
|
||||||
self.record_elided_anchor(t.id, t.span);
|
self.record_elided_anchor(t.id, t.span);
|
||||||
visit::walk_ty(self, t);
|
visit::walk_ty(self, t);
|
||||||
}
|
}
|
||||||
|
@ -547,6 +547,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||||
gate_all!(global_registration, "global registration is experimental");
|
gate_all!(global_registration, "global registration is experimental");
|
||||||
gate_all!(return_type_notation, "return type notation is experimental");
|
gate_all!(return_type_notation, "return type notation is experimental");
|
||||||
|
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||||
|
|
||||||
if !visitor.features.never_patterns {
|
if !visitor.features.never_patterns {
|
||||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||||
|
@ -1163,6 +1163,12 @@ impl<'a> State<'a> {
|
|||||||
self.print_opt_lifetime(lifetime);
|
self.print_opt_lifetime(lifetime);
|
||||||
self.print_mt(mt, false);
|
self.print_mt(mt, false);
|
||||||
}
|
}
|
||||||
|
ast::TyKind::PinnedRef(lifetime, mt) => {
|
||||||
|
self.word("&");
|
||||||
|
self.print_opt_lifetime(lifetime);
|
||||||
|
self.word("pin ");
|
||||||
|
self.print_mt(mt, true);
|
||||||
|
}
|
||||||
ast::TyKind::Never => {
|
ast::TyKind::Never => {
|
||||||
self.word("!");
|
self.word("!");
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_ast::util::parser::ExprPrecedence;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind,
|
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
|
||||||
TraitObjectSyntax, UintTy,
|
LitKind, TraitObjectSyntax, UintTy,
|
||||||
};
|
};
|
||||||
pub use rustc_ast::{
|
pub use rustc_ast::{
|
||||||
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
|
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
|
||||||
|
@ -2,9 +2,7 @@ use rustc_ast::ptr::P;
|
|||||||
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
|
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
|
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID
|
||||||
GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
|
|
||||||
PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
|
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_span::symbol::{Ident, kw, sym};
|
use rustc_span::symbol::{Ident, kw, sym};
|
||||||
@ -529,7 +527,10 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
|
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
|
||||||
let and_span = self.prev_token.span;
|
let and_span = self.prev_token.span;
|
||||||
let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
|
let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
|
||||||
let mut mutbl = self.parse_mutability();
|
let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
|
||||||
|
Some(pin_mut) => pin_mut,
|
||||||
|
None => (Pinnedness::Not, self.parse_mutability()),
|
||||||
|
};
|
||||||
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
|
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
|
||||||
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
|
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
|
||||||
// it to be followed by a plus, but we disallow plus in the pointee type.
|
// it to be followed by a plus, but we disallow plus in the pointee type.
|
||||||
@ -565,7 +566,35 @@ impl<'a> Parser<'a> {
|
|||||||
self.bump_with((dyn_tok, dyn_tok_sp));
|
self.bump_with((dyn_tok, dyn_tok_sp));
|
||||||
}
|
}
|
||||||
let ty = self.parse_ty_no_plus()?;
|
let ty = self.parse_ty_no_plus()?;
|
||||||
Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }))
|
Ok(match pinned {
|
||||||
|
Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
|
||||||
|
Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses `pin` and `mut` annotations on references.
|
||||||
|
///
|
||||||
|
/// It must be either `pin const` or `pin mut`.
|
||||||
|
pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
|
||||||
|
if self.token.is_ident_named(sym::pin) {
|
||||||
|
let result = self.look_ahead(1, |token| {
|
||||||
|
if token.is_keyword(kw::Const) {
|
||||||
|
Some((Pinnedness::Pinned, Mutability::Not))
|
||||||
|
} else if token.is_keyword(kw::Mut) {
|
||||||
|
Some((Pinnedness::Pinned, Mutability::Mut))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if result.is_some() {
|
||||||
|
self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
|
||||||
|
self.bump();
|
||||||
|
self.bump();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses the `typeof(EXPR)`.
|
// Parses the `typeof(EXPR)`.
|
||||||
|
@ -574,29 +574,33 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &'v ast::Ty) {
|
fn visit_ty(&mut self, t: &'v ast::Ty) {
|
||||||
record_variants!((self, t, t.kind, Id::None, ast, Ty, TyKind), [
|
record_variants!(
|
||||||
Slice,
|
(self, t, t.kind, Id::None, ast, Ty, TyKind),
|
||||||
Array,
|
[
|
||||||
Ptr,
|
Slice,
|
||||||
Ref,
|
Array,
|
||||||
BareFn,
|
Ptr,
|
||||||
Never,
|
Ref,
|
||||||
Tup,
|
PinnedRef,
|
||||||
AnonStruct,
|
BareFn,
|
||||||
AnonUnion,
|
Never,
|
||||||
Path,
|
Tup,
|
||||||
Pat,
|
AnonStruct,
|
||||||
TraitObject,
|
AnonUnion,
|
||||||
ImplTrait,
|
Path,
|
||||||
Paren,
|
Pat,
|
||||||
Typeof,
|
TraitObject,
|
||||||
Infer,
|
ImplTrait,
|
||||||
ImplicitSelf,
|
Paren,
|
||||||
MacCall,
|
Typeof,
|
||||||
CVarArgs,
|
Infer,
|
||||||
Dummy,
|
ImplicitSelf,
|
||||||
Err
|
MacCall,
|
||||||
]);
|
CVarArgs,
|
||||||
|
Dummy,
|
||||||
|
Err
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
ast_visit::walk_ty(self, t)
|
ast_visit::walk_ty(self, t)
|
||||||
}
|
}
|
||||||
|
@ -779,7 +779,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
|||||||
let prev = self.diag_metadata.current_trait_object;
|
let prev = self.diag_metadata.current_trait_object;
|
||||||
let prev_ty = self.diag_metadata.current_type_path;
|
let prev_ty = self.diag_metadata.current_type_path;
|
||||||
match &ty.kind {
|
match &ty.kind {
|
||||||
TyKind::Ref(None, _) => {
|
TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
|
||||||
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
|
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
|
||||||
// NodeId `ty.id`.
|
// NodeId `ty.id`.
|
||||||
// This span will be used in case of elision failure.
|
// This span will be used in case of elision failure.
|
||||||
@ -2326,7 +2326,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> {
|
impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> {
|
||||||
fn visit_ty(&mut self, ty: &'ra Ty) {
|
fn visit_ty(&mut self, ty: &'ra Ty) {
|
||||||
trace!("FindReferenceVisitor considering ty={:?}", ty);
|
trace!("FindReferenceVisitor considering ty={:?}", ty);
|
||||||
if let TyKind::Ref(lt, _) = ty.kind {
|
if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind {
|
||||||
// See if anything inside the &thing contains Self
|
// See if anything inside the &thing contains Self
|
||||||
let mut visitor =
|
let mut visitor =
|
||||||
SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
|
SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
|
||||||
|
@ -3482,7 +3482,7 @@ struct LifetimeFinder<'ast> {
|
|||||||
|
|
||||||
impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> {
|
impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> {
|
||||||
fn visit_ty(&mut self, t: &'ast Ty) {
|
fn visit_ty(&mut self, t: &'ast Ty) {
|
||||||
if let TyKind::Ref(_, mut_ty) = &t.kind {
|
if let TyKind::Ref(_, mut_ty) | TyKind::PinnedRef(_, mut_ty) = &t.kind {
|
||||||
self.seen.push(t);
|
self.seen.push(t);
|
||||||
if t.span.lo() == self.lifetime.lo() {
|
if t.span.lo() == self.lifetime.lo() {
|
||||||
self.found = Some(&mut_ty.ty);
|
self.found = Some(&mut_ty.ty);
|
||||||
|
@ -753,6 +753,9 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
|
|||||||
(Ref(ll, l), Ref(rl, r)) => {
|
(Ref(ll, l), Ref(rl, r)) => {
|
||||||
both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty)
|
both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty)
|
||||||
},
|
},
|
||||||
|
(PinnedRef(ll, l), PinnedRef(rl, r)) => {
|
||||||
|
both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty)
|
||||||
|
},
|
||||||
(BareFn(l), BareFn(r)) => {
|
(BareFn(l), BareFn(r)) => {
|
||||||
l.safety == r.safety
|
l.safety == r.safety
|
||||||
&& eq_ext(&l.ext, &r.ext)
|
&& eq_ext(&l.ext, &r.ext)
|
||||||
|
@ -827,7 +827,8 @@ impl Rewrite for ast::Ty {
|
|||||||
|
|
||||||
rewrite_unary_prefix(context, prefix, &*mt.ty, shape)
|
rewrite_unary_prefix(context, prefix, &*mt.ty, shape)
|
||||||
}
|
}
|
||||||
ast::TyKind::Ref(ref lifetime, ref mt) => {
|
ast::TyKind::Ref(ref lifetime, _pinned, ref mt) => {
|
||||||
|
// FIXME: format pinnedness
|
||||||
let mut_str = format_mutability(mt.mutbl);
|
let mut_str = format_mutability(mt.mutbl);
|
||||||
let mut_len = mut_str.len();
|
let mut_len = mut_str.len();
|
||||||
let mut result = String::with_capacity(128);
|
let mut result = String::with_capacity(128);
|
||||||
@ -1262,7 +1263,7 @@ pub(crate) fn can_be_overflowed_type(
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
ast::TyKind::Tup(..) => context.use_block_indent() && len == 1,
|
ast::TyKind::Tup(..) => context.use_block_indent() && len == 1,
|
||||||
ast::TyKind::Ref(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => {
|
ast::TyKind::Ref(_, _, ref mutty) | ast::TyKind::Ptr(ref mutty) => {
|
||||||
can_be_overflowed_type(context, &*mutty.ty, len)
|
can_be_overflowed_type(context, &*mutty.ty, len)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
15
tests/ui/async-await/pin-sugar-ambiguity.rs
Normal file
15
tests/ui/async-await/pin-sugar-ambiguity.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//@ check-pass
|
||||||
|
#![feature(pin_ergonomics)]
|
||||||
|
#![allow(dead_code, incomplete_features)]
|
||||||
|
|
||||||
|
// Handle the case where there's ambiguity between pin as a contextual keyword and pin as a path.
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
mod pin {
|
||||||
|
pub struct Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x: &pin ::Foo = &pin::Foo;
|
||||||
|
}
|
8
tests/ui/async-await/pin-sugar-no-const.rs
Normal file
8
tests/ui/async-await/pin-sugar-no-const.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#![feature(pin_ergonomics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// Makes sure we don't accidentally accept `&pin Foo` without the `const` keyword.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x: &pin i32 = todo!(); //~ ERROR found `i32`
|
||||||
|
}
|
15
tests/ui/async-await/pin-sugar-no-const.stderr
Normal file
15
tests/ui/async-await/pin-sugar-no-const.stderr
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error: expected one of `!`, `(`, `::`, `;`, `<`, or `=`, found `i32`
|
||||||
|
--> $DIR/pin-sugar-no-const.rs:7:18
|
||||||
|
|
|
||||||
|
LL | let _x: &pin i32 = todo!();
|
||||||
|
| - ^^^ expected one of `!`, `(`, `::`, `;`, `<`, or `=`
|
||||||
|
| |
|
||||||
|
| while parsing the type for `_x`
|
||||||
|
|
|
||||||
|
help: there is a keyword `in` with a similar name
|
||||||
|
|
|
||||||
|
LL | let _x: &in i32 = todo!();
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
51
tests/ui/async-await/pin-sugar.rs
Normal file
51
tests/ui/async-await/pin-sugar.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(pin_ergonomics)]
|
||||||
|
#![allow(dead_code, incomplete_features)]
|
||||||
|
|
||||||
|
// Makes sure we can handle `&pin mut T` and `&pin const T` as sugar for `Pin<&mut T>` and
|
||||||
|
// `Pin<&T>`.
|
||||||
|
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn baz(self: &pin mut Self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn baz_const(self: &pin const Self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn baz_lt<'a>(self: &'a pin mut Self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn baz_const_lt(self: &'_ pin const Self) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(_: &pin mut Foo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo_const(x: &pin const Foo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar(x: &pin mut Foo) {
|
||||||
|
foo(x);
|
||||||
|
foo(x); // for this to work we need to automatically reborrow,
|
||||||
|
// as if the user had written `foo(x.as_mut())`.
|
||||||
|
|
||||||
|
Foo::baz(x);
|
||||||
|
Foo::baz(x);
|
||||||
|
|
||||||
|
// make sure we can reborrow &mut as &.
|
||||||
|
foo_const(x);
|
||||||
|
Foo::baz_const(x);
|
||||||
|
|
||||||
|
let x: &pin const _ = Pin::new(&Foo);
|
||||||
|
|
||||||
|
foo_const(x); // make sure reborrowing from & to & works.
|
||||||
|
foo_const(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,4 +1,4 @@
|
|||||||
#![allow(dead_code, incomplete_features)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
@ -9,10 +9,13 @@ impl Foo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo(_: Pin<&mut Foo>) {
|
fn foo(x: Pin<&mut Foo>) {
|
||||||
|
let _y: &pin mut Foo = x; //~ ERROR pinned reference syntax is experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar(mut x: Pin<&mut Foo>) {
|
fn foo_sugar(_: &pin mut Foo) {} //~ ERROR pinned reference syntax is experimental
|
||||||
|
|
||||||
|
fn bar(x: Pin<&mut Foo>) {
|
||||||
foo(x);
|
foo(x);
|
||||||
foo(x); //~ ERROR use of moved value: `x`
|
foo(x); //~ ERROR use of moved value: `x`
|
||||||
}
|
}
|
||||||
@ -22,4 +25,6 @@ fn baz(mut x: Pin<&mut Foo>) {
|
|||||||
x.foo(); //~ ERROR use of moved value: `x`
|
x.foo(); //~ ERROR use of moved value: `x`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn baz_sugar(_: &pin const Foo) {} //~ ERROR pinned reference syntax is experimental
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,38 @@
|
|||||||
error[E0382]: use of moved value: `x`
|
error[E0658]: pinned reference syntax is experimental
|
||||||
--> $DIR/feature-gate-pin_ergonomics.rs:17:9
|
--> $DIR/feature-gate-pin_ergonomics.rs:13:14
|
||||||
|
|
|
|
||||||
LL | fn bar(mut x: Pin<&mut Foo>) {
|
LL | let _y: &pin mut Foo = x;
|
||||||
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
| ^^^
|
||||||
|
|
|
||||||
|
= 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]: pinned reference syntax is experimental
|
||||||
|
--> $DIR/feature-gate-pin_ergonomics.rs:16:18
|
||||||
|
|
|
||||||
|
LL | fn foo_sugar(_: &pin mut Foo) {}
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= 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]: pinned reference syntax is experimental
|
||||||
|
--> $DIR/feature-gate-pin_ergonomics.rs:28:18
|
||||||
|
|
|
||||||
|
LL | fn baz_sugar(_: &pin const Foo) {}
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= 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:20:9
|
||||||
|
|
|
||||||
|
LL | fn bar(x: Pin<&mut Foo>) {
|
||||||
|
| - move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
||||||
LL | foo(x);
|
LL | foo(x);
|
||||||
| - value moved here
|
| - value moved here
|
||||||
LL | foo(x);
|
LL | foo(x);
|
||||||
@ -11,13 +41,13 @@ LL | foo(x);
|
|||||||
note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary
|
note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary
|
||||||
--> $DIR/feature-gate-pin_ergonomics.rs:12:11
|
--> $DIR/feature-gate-pin_ergonomics.rs:12:11
|
||||||
|
|
|
|
||||||
LL | fn foo(_: Pin<&mut Foo>) {
|
LL | fn foo(x: Pin<&mut Foo>) {
|
||||||
| --- ^^^^^^^^^^^^^ this parameter takes ownership of the value
|
| --- ^^^^^^^^^^^^^ this parameter takes ownership of the value
|
||||||
| |
|
| |
|
||||||
| in this function
|
| in this function
|
||||||
|
|
||||||
error[E0382]: use of moved value: `x`
|
error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/feature-gate-pin_ergonomics.rs:22:5
|
--> $DIR/feature-gate-pin_ergonomics.rs:25:5
|
||||||
|
|
|
|
||||||
LL | fn baz(mut x: Pin<&mut Foo>) {
|
LL | fn baz(mut x: Pin<&mut Foo>) {
|
||||||
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
| ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
||||||
@ -36,6 +66,7 @@ help: consider reborrowing the `Pin` instead of moving it
|
|||||||
LL | x.as_mut().foo();
|
LL | x.as_mut().foo();
|
||||||
| +++++++++
|
| +++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0382`.
|
Some errors have detailed explanations: E0382, E0658.
|
||||||
|
For more information about an error, try `rustc --explain E0382`.
|
||||||
|
Loading…
Reference in New Issue
Block a user