Auto merge of #131724 - matthiaskrgr:rollup-ntgkkk8, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #130608 (Implemented `FromStr` for `CString` and `TryFrom<CString>` for `String`) - #130635 (Add `&pin (mut|const) T` type position sugar) - #130747 (improve error messages for `C-cmse-nonsecure-entry` functions) - #131137 (Add 1.82 release notes) - #131328 (Remove unnecessary sorts in `rustc_hir_analysis`) - #131496 (Stabilise `const_make_ascii`.) - #131706 (Fix two const-hacks) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
88f311479d
50 changed files with 1126 additions and 185 deletions
|
@ -23,7 +23,7 @@ use std::{cmp, fmt, mem};
|
|||
|
||||
pub use GenericArgs::*;
|
||||
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::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
@ -2161,6 +2161,10 @@ pub enum TyKind {
|
|||
Ptr(MutTy),
|
||||
/// A reference (`&'a T` or `&'a mut T`).
|
||||
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`).
|
||||
BareFn(P<BareFnTy>),
|
||||
/// The never type (`!`).
|
||||
|
@ -2501,7 +2505,10 @@ impl Param {
|
|||
if ident.name == kw::SelfLower {
|
||||
return match self.ty.kind {
|
||||
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(
|
||||
|
|
|
@ -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::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));
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -499,7 +499,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
|||
match kind {
|
||||
TyKind::Slice(ty) | TyKind::Paren(ty) => 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);
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
}
|
||||
|
|
|
@ -79,3 +79,10 @@ impl Mutability {
|
|||
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),
|
||||
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 {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::TyKind::Path(resume_ty),
|
||||
|
@ -2065,7 +2066,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
lang_item: hir::LangItem,
|
||||
name: Symbol,
|
||||
) -> 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(
|
||||
self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
|
||||
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_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::{
|
||||
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName,
|
||||
TraitCandidate,
|
||||
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind,
|
||||
ParamName, TraitCandidate,
|
||||
};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::extension;
|
||||
|
@ -765,8 +765,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
res
|
||||
}
|
||||
|
||||
fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> {
|
||||
hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, None))
|
||||
fn make_lang_item_qpath(
|
||||
&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(
|
||||
|
@ -1277,6 +1282,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let lifetime = self.lower_lifetime(®ion);
|
||||
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) => {
|
||||
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
|
||||
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
|
||||
|
@ -1845,10 +1876,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// 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
|
||||
// no longer be an `ImplicitSelf`.
|
||||
TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl {
|
||||
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
|
||||
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
|
||||
},
|
||||
TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt)
|
||||
if mt.ty.kind.is_implicit_self() =>
|
||||
{
|
||||
match mt.mutbl {
|
||||
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
|
||||
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
|
||||
}
|
||||
}
|
||||
_ => hir::ImplicitSelfKind::None,
|
||||
}
|
||||
}),
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> {
|
|||
visit::walk_ty(self, t);
|
||||
self.current_binders.pop();
|
||||
}
|
||||
TyKind::Ref(None, _) => {
|
||||
TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
|
||||
self.record_elided_anchor(t.id, t.span);
|
||||
visit::walk_ty(self, t);
|
||||
}
|
||||
|
|
|
@ -546,6 +546,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(global_registration, "global registration 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 let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
|
|
@ -1163,6 +1163,12 @@ impl<'a> State<'a> {
|
|||
self.print_opt_lifetime(lifetime);
|
||||
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 => {
|
||||
self.word("!");
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fmt;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::util::parser::ExprPrecedence;
|
||||
use rustc_ast::{
|
||||
Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind,
|
||||
TraitObjectSyntax, UintTy,
|
||||
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
|
||||
LitKind, TraitObjectSyntax, UintTy,
|
||||
};
|
||||
pub use rustc_ast::{
|
||||
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
|
||||
|
|
|
@ -68,18 +68,21 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo
|
|||
hir_analysis_cmse_call_generic =
|
||||
function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
|
||||
|
||||
hir_analysis_cmse_call_inputs_stack_spill =
|
||||
arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
|
||||
hir_analysis_cmse_entry_generic =
|
||||
functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
|
||||
|
||||
hir_analysis_cmse_inputs_stack_spill =
|
||||
arguments for `"{$abi_name}"` function too large to pass via registers
|
||||
.label = {$plural ->
|
||||
[false] this argument doesn't
|
||||
*[true] these arguments don't
|
||||
} fit in the available registers
|
||||
.note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
|
||||
.note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers
|
||||
|
||||
hir_analysis_cmse_call_output_stack_spill =
|
||||
return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
|
||||
hir_analysis_cmse_output_stack_spill =
|
||||
return value of `"{$abi_name}"` function too large to pass via registers
|
||||
.label = this type doesn't fit in the available registers
|
||||
.note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
|
||||
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
|
||||
|
|
|
@ -531,7 +531,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
debug!(?required_bounds);
|
||||
let param_env = tcx.param_env(gat_def_id);
|
||||
|
||||
let mut unsatisfied_bounds: Vec<_> = required_bounds
|
||||
let unsatisfied_bounds: Vec<_> = required_bounds
|
||||
.into_iter()
|
||||
.filter(|clause| match clause.kind().skip_binder() {
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
|
||||
|
@ -552,9 +552,6 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
|
|||
.map(|clause| clause.to_string())
|
||||
.collect();
|
||||
|
||||
// We sort so that order is predictable
|
||||
unsatisfied_bounds.sort();
|
||||
|
||||
if !unsatisfied_bounds.is_empty() {
|
||||
let plural = pluralize!(unsatisfied_bounds.len());
|
||||
let suggestion = format!(
|
||||
|
|
|
@ -319,9 +319,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
|||
// List of connected regions is built. Now, run the overlap check
|
||||
// for each pair of impl blocks in the same connected region.
|
||||
for region in connected_regions.into_iter().flatten() {
|
||||
let mut impl_blocks =
|
||||
region.impl_blocks.into_iter().collect::<SmallVec<[usize; 8]>>();
|
||||
impl_blocks.sort_unstable();
|
||||
let impl_blocks = region.impl_blocks.into_iter().collect::<SmallVec<[usize; 8]>>();
|
||||
for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
|
||||
let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
|
||||
res = res.and(self.check_for_duplicate_items_in_impl(impl1_def_id));
|
||||
|
|
|
@ -1627,23 +1627,25 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
|
|||
pub(crate) struct EffectsWithoutNextSolver;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)]
|
||||
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
|
||||
#[note]
|
||||
pub(crate) struct CmseCallInputsStackSpill {
|
||||
pub(crate) struct CmseInputsStackSpill {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub plural: bool,
|
||||
pub abi_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
|
||||
#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)]
|
||||
#[note(hir_analysis_note1)]
|
||||
#[note(hir_analysis_note2)]
|
||||
pub(crate) struct CmseCallOutputStackSpill {
|
||||
pub(crate) struct CmseOutputStackSpill {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub abi_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -1659,3 +1661,10 @@ pub(crate) struct BadReturnTypeNotation {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_cmse_entry_generic, code = E0798)]
|
||||
pub(crate) struct CmseEntryGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
|
||||
use crate::errors;
|
||||
|
@ -17,61 +17,104 @@ pub(crate) fn validate_cmse_abi<'tcx>(
|
|||
abi: abi::Abi,
|
||||
fn_sig: ty::PolyFnSig<'tcx>,
|
||||
) {
|
||||
if let abi::Abi::CCmseNonSecureCall = abi {
|
||||
let hir_node = tcx.hir_node(hir_id);
|
||||
let hir::Node::Ty(hir::Ty {
|
||||
span: bare_fn_span,
|
||||
kind: hir::TyKind::BareFn(bare_fn_ty),
|
||||
..
|
||||
}) = hir_node
|
||||
else {
|
||||
let span = match tcx.parent_hir_node(hir_id) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::ForeignMod { .. }, span, ..
|
||||
}) => *span,
|
||||
_ => tcx.hir().span(hir_id),
|
||||
let abi_name = abi.name();
|
||||
|
||||
match abi {
|
||||
abi::Abi::CCmseNonSecureCall => {
|
||||
let hir_node = tcx.hir_node(hir_id);
|
||||
let hir::Node::Ty(hir::Ty {
|
||||
span: bare_fn_span,
|
||||
kind: hir::TyKind::BareFn(bare_fn_ty),
|
||||
..
|
||||
}) = hir_node
|
||||
else {
|
||||
let span = match tcx.parent_hir_node(hir_id) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::ForeignMod { .. },
|
||||
span,
|
||||
..
|
||||
}) => *span,
|
||||
_ => tcx.hir().span(hir_id),
|
||||
};
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0781,
|
||||
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
};
|
||||
struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0781,
|
||||
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
};
|
||||
|
||||
match is_valid_cmse_inputs(tcx, fn_sig) {
|
||||
Ok(Ok(())) => {}
|
||||
Ok(Err(index)) => {
|
||||
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
|
||||
// ^^^^^^
|
||||
let span = bare_fn_ty.param_names[index]
|
||||
.span
|
||||
.to(bare_fn_ty.decl.inputs[index].span)
|
||||
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
||||
let plural = bare_fn_ty.param_names.len() - index != 1;
|
||||
dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
|
||||
dcx.emit_err(err);
|
||||
match is_valid_cmse_inputs(tcx, fn_sig) {
|
||||
Ok(Ok(())) => {}
|
||||
Ok(Err(index)) => {
|
||||
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
|
||||
// ^^^^^^
|
||||
let span = bare_fn_ty.param_names[index]
|
||||
.span
|
||||
.to(bare_fn_ty.decl.inputs[index].span)
|
||||
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
|
||||
let plural = bare_fn_ty.param_names.len() - index != 1;
|
||||
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if should_emit_generic_error(abi, layout_err) {
|
||||
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match is_valid_cmse_output(tcx, fn_sig) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let span = bare_fn_ty.decl.output.span();
|
||||
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if should_emit_generic_error(abi, layout_err) {
|
||||
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
abi::Abi::CCmseNonSecureEntry => {
|
||||
let hir_node = tcx.hir_node(hir_id);
|
||||
let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else {
|
||||
// might happen when this ABI is used incorrectly. That will be handled elsewhere
|
||||
return;
|
||||
};
|
||||
|
||||
match is_valid_cmse_output(tcx, fn_sig) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let span = bare_fn_ty.decl.output.span();
|
||||
dcx.emit_err(errors::CmseCallOutputStackSpill { span });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
|
||||
dcx.emit_err(err);
|
||||
match is_valid_cmse_inputs(tcx, fn_sig) {
|
||||
Ok(Ok(())) => {}
|
||||
Ok(Err(index)) => {
|
||||
// fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32,
|
||||
// ^^^^^^
|
||||
let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span);
|
||||
let plural = decl.inputs.len() - index != 1;
|
||||
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if should_emit_generic_error(abi, layout_err) {
|
||||
dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match is_valid_cmse_output(tcx, fn_sig) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let span = decl.output.span();
|
||||
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
|
||||
}
|
||||
Err(layout_err) => {
|
||||
if should_emit_generic_error(abi, layout_err) {
|
||||
dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,22 +195,22 @@ fn is_valid_cmse_output<'tcx>(
|
|||
Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64)
|
||||
}
|
||||
|
||||
fn cmse_layout_err<'tcx>(
|
||||
layout_err: &'tcx LayoutError<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<crate::errors::CmseCallGeneric> {
|
||||
fn should_emit_generic_error<'tcx>(abi: abi::Abi, layout_err: &'tcx LayoutError<'tcx>) -> bool {
|
||||
use LayoutError::*;
|
||||
|
||||
match layout_err {
|
||||
Unknown(ty) => {
|
||||
if ty.is_impl_trait() {
|
||||
None // prevent double reporting of this error
|
||||
} else {
|
||||
Some(errors::CmseCallGeneric { span })
|
||||
match abi {
|
||||
abi::Abi::CCmseNonSecureCall => {
|
||||
// prevent double reporting of this error
|
||||
!ty.is_impl_trait()
|
||||
}
|
||||
abi::Abi::CCmseNonSecureEntry => true,
|
||||
_ => bug!("invalid ABI: {abi}"),
|
||||
}
|
||||
}
|
||||
SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
|
||||
None // not our job to report these
|
||||
false // not our job to report these
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ use rustc_ast::util::case::Case;
|
|||
use rustc_ast::{
|
||||
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
|
||||
GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
|
||||
PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
|
||||
Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
|
||||
TyKind,
|
||||
};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
|
@ -487,7 +488,10 @@ impl<'a> Parser<'a> {
|
|||
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
|
||||
let and_span = self.prev_token.span;
|
||||
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() {
|
||||
// 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.
|
||||
|
@ -523,7 +527,35 @@ impl<'a> Parser<'a> {
|
|||
self.bump_with((dyn_tok, dyn_tok_sp));
|
||||
}
|
||||
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)`.
|
||||
|
|
|
@ -579,6 +579,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
Array,
|
||||
Ptr,
|
||||
Ref,
|
||||
PinnedRef,
|
||||
BareFn,
|
||||
Never,
|
||||
Tup,
|
||||
|
|
|
@ -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_ty = self.diag_metadata.current_type_path;
|
||||
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
|
||||
// NodeId `ty.id`.
|
||||
// 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<'_, '_, '_> {
|
||||
fn visit_ty(&mut self, ty: &'ra 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
|
||||
let mut visitor =
|
||||
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> {
|
||||
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);
|
||||
if t.span.lo() == self.lifetime.lo() {
|
||||
self.found = Some(&mut_ty.ty);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue