Merge ref '1553adfe68' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.
Upstream ref: 1553adfe68
Filtered ref: e5ee70aa5f36dacdc6df9490e867c45aa4e51c18
This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
4b5f667dc4
698 changed files with 11152 additions and 6367 deletions
12
.github/ISSUE_TEMPLATE/documentation.yaml
vendored
12
.github/ISSUE_TEMPLATE/documentation.yaml
vendored
|
|
@ -1,5 +1,5 @@
|
|||
name: Documentation problem
|
||||
description: Create a report for a documentation problem.
|
||||
description: Report an issue with documentation content.
|
||||
labels: ["A-docs"]
|
||||
body:
|
||||
- type: markdown
|
||||
|
|
@ -19,20 +19,20 @@ body:
|
|||
- [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
|
||||
- [The Embedded Book](https://github.com/rust-embedded/book/issues)
|
||||
|
||||
All other documentation issues should be filed here.
|
||||
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the rustdoc issue template instead.
|
||||
|
||||
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
|
||||
All other documentation issues should be filed here.
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Location
|
||||
label: Location (URL)
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Summary
|
||||
validations:
|
||||
required: true
|
||||
required: true
|
||||
|
|
|
|||
|
|
@ -5284,9 +5284,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.36.1"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
|
||||
checksum = "07cec4dc2d2e357ca1e610cfb07de2fa7a10fc3e9fe89f72545f3d244ea87753"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
|
|
|
|||
|
|
@ -740,11 +740,19 @@
|
|||
# result (broken, compiling, testing) into this JSON file.
|
||||
#rust.save-toolstates = <none> (path)
|
||||
|
||||
# This is an array of the codegen backends that will be compiled for the rustc
|
||||
# that's being compiled. The default is to only build the LLVM codegen backend,
|
||||
# and currently the only standard options supported are `"llvm"`, `"cranelift"`
|
||||
# and `"gcc"`. The first backend in this list will be used as default by rustc
|
||||
# when no explicit backend is specified.
|
||||
# This array serves three distinct purposes:
|
||||
# - Backends in this list will be automatically compiled and included in the sysroot of each
|
||||
# rustc compiled by bootstrap.
|
||||
# - The first backend in this list will be configured as the **default codegen backend** by each
|
||||
# rustc compiled by bootstrap. In other words, if the first backend is e.g. cranelift, then when
|
||||
# we build a stage 1 rustc, it will by default compile Rust programs using the Cranelift backend.
|
||||
# This also means that stage 2 rustc would get built by the Cranelift backend.
|
||||
# - Running `x dist` (without additional arguments, or with `--include-default-paths`) will produce
|
||||
# a dist component/tarball for the Cranelift backend if it is included in this array.
|
||||
#
|
||||
# Note that the LLVM codegen backend is special and will always be built and distributed.
|
||||
#
|
||||
# Currently, the only standard options supported here are `"llvm"`, `"cranelift"` and `"gcc"`.
|
||||
#rust.codegen-backends = ["llvm"]
|
||||
|
||||
# Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,6 @@
|
|||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::LazyAttrTokenStream;
|
||||
use crate::{
|
||||
Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
|
||||
|
|
@ -53,7 +52,7 @@ impl_has_node_id!(
|
|||
WherePredicate,
|
||||
);
|
||||
|
||||
impl<T: HasNodeId> HasNodeId for P<T> {
|
||||
impl<T: HasNodeId> HasNodeId for Box<T> {
|
||||
fn node_id(&self) -> NodeId {
|
||||
(**self).node_id()
|
||||
}
|
||||
|
|
@ -119,7 +118,7 @@ impl<T: HasTokens> HasTokens for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: HasTokens> HasTokens for P<T> {
|
||||
impl<T: HasTokens> HasTokens for Box<T> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
(**self).tokens()
|
||||
}
|
||||
|
|
@ -245,7 +244,7 @@ impl_has_attrs!(
|
|||
);
|
||||
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
|
||||
|
||||
impl<T: HasAttrs> HasAttrs for P<T> {
|
||||
impl<T: HasAttrs> HasAttrs for Box<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
(**self).attrs()
|
||||
|
|
@ -322,8 +321,8 @@ impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> {
|
|||
}
|
||||
|
||||
// FIXME: remove after `stmt_expr_attributes` is stabilized.
|
||||
impl<T, Tag> From<AstNodeWrapper<P<T>, Tag>> for AstNodeWrapper<T, Tag> {
|
||||
fn from(value: AstNodeWrapper<P<T>, Tag>) -> Self {
|
||||
impl<T, Tag> From<AstNodeWrapper<Box<T>, Tag>> for AstNodeWrapper<T, Tag> {
|
||||
fn from(value: AstNodeWrapper<Box<T>, Tag>) -> Self {
|
||||
AstNodeWrapper { wrapped: *value.wrapped, tag: value.tag }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use crate::ast::{
|
|||
Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
|
||||
PathSegment, Safety,
|
||||
};
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Delimiter, InvisibleOrigin, MetaVarKind, Token};
|
||||
use crate::tokenstream::{
|
||||
DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenStreamIter, TokenTree,
|
||||
|
|
@ -660,7 +659,7 @@ pub fn mk_attr_from_item(
|
|||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
|
||||
kind: AttrKind::Normal(Box::new(NormalAttr { item, tokens })),
|
||||
id: g.mk_attr_id(),
|
||||
style,
|
||||
span,
|
||||
|
|
@ -710,7 +709,7 @@ pub fn mk_attr_name_value_str(
|
|||
span: Span,
|
||||
) -> Attribute {
|
||||
let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
|
||||
let expr = P(Expr {
|
||||
let expr = Box::new(Expr {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: ExprKind::Lit(lit),
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::fmt::{self, Display, Formatter};
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::expand::{Decodable, Encodable, HashStable_Generic};
|
||||
use crate::ptr::P;
|
||||
use crate::{Ty, TyKind};
|
||||
|
||||
/// Forward and Reverse Mode are well known names for automatic differentiation implementations.
|
||||
|
|
@ -162,7 +161,7 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
|
|||
/// since Duplicated expects a mutable ref/ptr and we would thus end up with a shadow value
|
||||
/// who is an indirect type, which doesn't match the primal scalar type. We can't prevent
|
||||
/// users here from marking scalars as Duplicated, due to type aliases.
|
||||
pub fn valid_ty_for_activity(ty: &P<Ty>, activity: DiffActivity) -> bool {
|
||||
pub fn valid_ty_for_activity(ty: &Box<Ty>, activity: DiffActivity) -> bool {
|
||||
use DiffActivity::*;
|
||||
// It's always allowed to mark something as Const, since we won't compute derivatives wrt. it.
|
||||
// Dual variants also support all types.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use rustc_macros::{Decodable, Encodable, Walkable};
|
|||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::Expr;
|
||||
use crate::ptr::P;
|
||||
use crate::token::LitKind;
|
||||
|
||||
// Definitions:
|
||||
|
|
@ -147,7 +146,7 @@ impl FormatArguments {
|
|||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct FormatArgument {
|
||||
pub kind: FormatArgumentKind,
|
||||
pub expr: P<Expr>,
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ pub mod expand;
|
|||
pub mod format;
|
||||
pub mod mut_visit;
|
||||
pub mod node_id;
|
||||
pub mod ptr;
|
||||
pub mod token;
|
||||
pub mod tokenstream;
|
||||
pub mod visit;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec};
|
|||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::*;
|
||||
use crate::visit::{AssocCtxt, BoundKind, FnCtxt, LifetimeCtxt, VisitorResult, try_visit};
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ pub(crate) trait MutVisitable<V: MutVisitor> {
|
|||
fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra);
|
||||
}
|
||||
|
||||
impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for P<T>
|
||||
impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for Box<T>
|
||||
where
|
||||
T: MutVisitable<V>,
|
||||
{
|
||||
|
|
@ -293,15 +292,15 @@ macro_rules! generate_flat_map_visitor_fns {
|
|||
}
|
||||
|
||||
generate_flat_map_visitor_fns! {
|
||||
visit_items, P<Item>, flat_map_item;
|
||||
visit_foreign_items, P<ForeignItem>, flat_map_foreign_item;
|
||||
visit_items, Box<Item>, flat_map_item;
|
||||
visit_foreign_items, Box<ForeignItem>, flat_map_foreign_item;
|
||||
visit_generic_params, GenericParam, flat_map_generic_param;
|
||||
visit_stmts, Stmt, flat_map_stmt;
|
||||
visit_exprs, P<Expr>, filter_map_expr;
|
||||
visit_exprs, Box<Expr>, filter_map_expr;
|
||||
visit_expr_fields, ExprField, flat_map_expr_field;
|
||||
visit_pat_fields, PatField, flat_map_pat_field;
|
||||
visit_variants, Variant, flat_map_variant;
|
||||
visit_assoc_items, P<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
|
||||
visit_assoc_items, Box<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
|
||||
visit_where_predicates, WherePredicate, flat_map_where_predicate;
|
||||
visit_params, Param, flat_map_param;
|
||||
visit_field_defs, FieldDef, flat_map_field_def;
|
||||
|
|
@ -333,12 +332,12 @@ generate_walk_flat_map_fns! {
|
|||
walk_flat_map_where_predicate(WherePredicate) => visit_where_predicate;
|
||||
walk_flat_map_field_def(FieldDef) => visit_field_def;
|
||||
walk_flat_map_expr_field(ExprField) => visit_expr_field;
|
||||
walk_flat_map_item(P<Item>) => visit_item;
|
||||
walk_flat_map_foreign_item(P<ForeignItem>) => visit_foreign_item;
|
||||
walk_flat_map_assoc_item(P<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
|
||||
walk_flat_map_item(Box<Item>) => visit_item;
|
||||
walk_flat_map_foreign_item(Box<ForeignItem>) => visit_foreign_item;
|
||||
walk_flat_map_assoc_item(Box<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
|
||||
}
|
||||
|
||||
pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
|
||||
pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: Box<Expr>) -> Option<Box<Expr>> {
|
||||
vis.visit_expr(&mut e);
|
||||
Some(e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
/// A pointer type that uniquely owns a heap allocation of type T.
|
||||
///
|
||||
/// This used to be its own type, but now it's just a typedef for `Box` and we are planning to
|
||||
/// remove it soon.
|
||||
pub type P<T> = Box<T>;
|
||||
|
||||
/// Construct a `P<T>` from a `T` value.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn P<T>(value: T) -> P<T> {
|
||||
Box::new(value)
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ use rustc_span::{Ident, Span, Symbol};
|
|||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
use crate::tokenstream::DelimSpan;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
|
@ -82,7 +81,7 @@ pub(crate) trait Visitable<'a, V: Visitor<'a>> {
|
|||
fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result;
|
||||
}
|
||||
|
||||
impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for P<T>
|
||||
impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for Box<T>
|
||||
where
|
||||
T: Visitable<'a, V>,
|
||||
{
|
||||
|
|
@ -322,7 +321,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),
|
||||
|
||||
/// E.g., `|x, y| body`.
|
||||
Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? P<FnDecl>, &'a $($mut)? P<Expr>),
|
||||
Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? Box<FnDecl>, &'a $($mut)? Box<Expr>),
|
||||
}
|
||||
|
||||
impl<'a> FnKind<'a> {
|
||||
|
|
@ -390,9 +389,9 @@ macro_rules! common_visitor_and_walkers {
|
|||
ThinVec<(NodeId, Path)>,
|
||||
ThinVec<PathSegment>,
|
||||
ThinVec<PreciseCapturingArg>,
|
||||
ThinVec<P<Pat>>,
|
||||
ThinVec<P<Ty>>,
|
||||
ThinVec<P<TyPat>>,
|
||||
ThinVec<Box<Pat>>,
|
||||
ThinVec<Box<Ty>>,
|
||||
ThinVec<Box<TyPat>>,
|
||||
);
|
||||
|
||||
// This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`
|
||||
|
|
@ -676,11 +675,11 @@ macro_rules! common_visitor_and_walkers {
|
|||
// Do nothing.
|
||||
}
|
||||
|
||||
fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
|
||||
fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {
|
||||
walk_flat_map_foreign_item(self, ni)
|
||||
}
|
||||
|
||||
fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
|
||||
fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {
|
||||
walk_flat_map_item(self, i)
|
||||
}
|
||||
|
||||
|
|
@ -690,9 +689,9 @@ macro_rules! common_visitor_and_walkers {
|
|||
|
||||
fn flat_map_assoc_item(
|
||||
&mut self,
|
||||
i: P<AssocItem>,
|
||||
i: Box<AssocItem>,
|
||||
ctxt: AssocCtxt,
|
||||
) -> SmallVec<[P<AssocItem>; 1]> {
|
||||
) -> SmallVec<[Box<AssocItem>; 1]> {
|
||||
walk_flat_map_assoc_item(self, i, ctxt)
|
||||
}
|
||||
|
||||
|
|
@ -704,7 +703,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
walk_flat_map_arm(self, arm)
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
|
||||
fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {
|
||||
walk_filter_map_expr(self, e)
|
||||
}
|
||||
|
||||
|
|
@ -930,8 +929,13 @@ macro_rules! common_visitor_and_walkers {
|
|||
}
|
||||
|
||||
impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
|
||||
let Impl { defaultness, safety, generics, constness, polarity, of_trait, self_ty, items } = self;
|
||||
visit_visitable!($($mut)? vis, defaultness, safety, generics, constness, polarity, of_trait, self_ty);
|
||||
let Impl { generics, of_trait, self_ty, items } = self;
|
||||
try_visit!(vis.visit_generics(generics));
|
||||
if let Some(box of_trait) = of_trait {
|
||||
let TraitImplHeader { defaultness, safety, constness, polarity, trait_ref } = of_trait;
|
||||
visit_visitable!($($mut)? vis, defaultness, safety, constness, polarity, trait_ref);
|
||||
}
|
||||
try_visit!(vis.visit_ty(self_ty));
|
||||
visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });
|
||||
V::Result::output()
|
||||
});
|
||||
|
|
@ -1144,15 +1148,15 @@ macro_rules! generate_list_visit_fns {
|
|||
}
|
||||
|
||||
generate_list_visit_fns! {
|
||||
visit_items, P<Item>, visit_item;
|
||||
visit_foreign_items, P<ForeignItem>, visit_foreign_item;
|
||||
visit_items, Box<Item>, visit_item;
|
||||
visit_foreign_items, Box<ForeignItem>, visit_foreign_item;
|
||||
visit_generic_params, GenericParam, visit_generic_param;
|
||||
visit_stmts, Stmt, visit_stmt;
|
||||
visit_exprs, P<Expr>, visit_expr;
|
||||
visit_exprs, Box<Expr>, visit_expr;
|
||||
visit_expr_fields, ExprField, visit_expr_field;
|
||||
visit_pat_fields, PatField, visit_pat_field;
|
||||
visit_variants, Variant, visit_variant;
|
||||
visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
|
||||
visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
|
||||
visit_where_predicates, WherePredicate, visit_where_predicate;
|
||||
visit_params, Param, visit_param;
|
||||
visit_field_defs, FieldDef, visit_field_def;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
| asm::InlineAsmArch::Arm64EC
|
||||
| asm::InlineAsmArch::RiscV32
|
||||
| asm::InlineAsmArch::RiscV64
|
||||
| asm::InlineAsmArch::LoongArch32
|
||||
| asm::InlineAsmArch::LoongArch64
|
||||
| asm::InlineAsmArch::S390x
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::ops::ControlFlow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::ptr::P as AstP;
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust::expr_to_string;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
|
@ -53,7 +52,7 @@ impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {
|
|||
}
|
||||
|
||||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
|
||||
fn lower_exprs(&mut self, exprs: &[Box<Expr>]) -> &'hir [hir::Expr<'hir>] {
|
||||
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +454,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn lower_legacy_const_generics(
|
||||
&mut self,
|
||||
mut f: Expr,
|
||||
args: ThinVec<AstP<Expr>>,
|
||||
args: ThinVec<Box<Expr>>,
|
||||
legacy_args_idx: &[usize],
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let ExprKind::Path(None, path) = &mut f.kind else {
|
||||
|
|
@ -495,7 +494,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.create_def(node_id, None, DefKind::AnonConst, f.span);
|
||||
let mut visitor = WillCreateDefIdsVisitor {};
|
||||
let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
|
||||
AstP(Expr {
|
||||
Box::new(Expr {
|
||||
id: self.next_node_id(),
|
||||
kind: ExprKind::Err(invalid_expr_error(self.tcx, span)),
|
||||
span: f.span,
|
||||
|
|
@ -516,7 +515,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// Add generic args to the last element of the path.
|
||||
let last_segment = path.segments.last_mut().unwrap();
|
||||
assert!(last_segment.args.is_none());
|
||||
last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
|
||||
last_segment.args = Some(Box::new(GenericArgs::AngleBracketed(AngleBracketedArgs {
|
||||
span: DUMMY_SP,
|
||||
args: generic_args,
|
||||
})));
|
||||
|
|
@ -812,7 +811,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_attrs(
|
||||
inner_hir_id,
|
||||
&[Attribute {
|
||||
kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(
|
||||
kind: AttrKind::Normal(Box::new(NormalAttr::from_ident(Ident::new(
|
||||
sym::track_caller,
|
||||
span,
|
||||
)))),
|
||||
|
|
@ -1285,7 +1284,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn extract_tuple_struct_path<'a>(
|
||||
&mut self,
|
||||
expr: &'a Expr,
|
||||
) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
|
||||
) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
|
||||
if let ExprKind::Path(qself, path) = &expr.kind {
|
||||
// Does the path resolve to something disallowed in a tuple struct/variant pattern?
|
||||
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
|
||||
|
|
@ -1307,7 +1306,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn extract_unit_struct_path<'a>(
|
||||
&mut self,
|
||||
expr: &'a Expr,
|
||||
) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
|
||||
) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
|
||||
if let ExprKind::Path(qself, path) = &expr.kind {
|
||||
// Does the path resolve to something disallowed in a unit struct/variant pattern?
|
||||
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
|
||||
|
|
@ -1478,7 +1477,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
/// Each sub-assignment is recorded in `assignments`.
|
||||
fn destructure_sequence(
|
||||
&mut self,
|
||||
elements: &[AstP<Expr>],
|
||||
elements: &[Box<Expr>],
|
||||
ctx: &str,
|
||||
eq_sign_span: Span,
|
||||
assignments: &mut Vec<hir::Stmt<'hir>>,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::AssocCtxt;
|
||||
use rustc_ast::*;
|
||||
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
|
||||
|
|
@ -102,7 +101,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
impl<'hir> LoweringContext<'_, 'hir> {
|
||||
pub(super) fn lower_mod(
|
||||
&mut self,
|
||||
items: &[P<Item>],
|
||||
items: &[Box<Item>],
|
||||
spans: &ModSpans,
|
||||
) -> &'hir hir::Mod<'hir> {
|
||||
self.arena.alloc(hir::Mod {
|
||||
|
|
@ -341,13 +340,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
);
|
||||
hir::ItemKind::Union(ident, generics, vdata)
|
||||
}
|
||||
ItemKind::Impl(box Impl {
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
constness,
|
||||
ItemKind::Impl(Impl {
|
||||
generics: ast_generics,
|
||||
of_trait: trait_ref,
|
||||
of_trait,
|
||||
self_ty: ty,
|
||||
items: impl_items,
|
||||
}) => {
|
||||
|
|
@ -365,54 +360,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// lifetime to be added, but rather a reference to a
|
||||
// parent lifetime.
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
let (generics, (of_trait, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, id, itctx, |this| {
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
};
|
||||
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
modifiers,
|
||||
trait_ref,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
)
|
||||
});
|
||||
let of_trait = of_trait
|
||||
.as_deref()
|
||||
.map(|of_trait| this.lower_trait_impl_header(of_trait));
|
||||
|
||||
let lowered_ty = this.lower_ty(
|
||||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
|
||||
);
|
||||
|
||||
(trait_ref, lowered_ty)
|
||||
(of_trait, lowered_ty)
|
||||
});
|
||||
|
||||
let new_impl_items = self
|
||||
.arena
|
||||
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
|
||||
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
let has_val = true;
|
||||
let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val);
|
||||
let polarity = match polarity {
|
||||
ImplPolarity::Positive => ImplPolarity::Positive,
|
||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
||||
};
|
||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||
constness: self.lower_constness(*constness),
|
||||
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span,
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
generics,
|
||||
of_trait: trait_ref,
|
||||
of_trait,
|
||||
self_ty: lowered_ty,
|
||||
items: new_impl_items,
|
||||
}))
|
||||
})
|
||||
}
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
|
|
@ -462,7 +433,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
let body = P(self.lower_delim_args(body));
|
||||
let body = Box::new(self.lower_delim_args(body));
|
||||
let def_id = self.local_def_id(id);
|
||||
let def_kind = self.tcx.def_kind(def_id);
|
||||
let DefKind::Macro(macro_kind) = def_kind else {
|
||||
|
|
@ -983,6 +954,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.expr(span, hir::ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
fn lower_trait_impl_header(
|
||||
&mut self,
|
||||
trait_impl_header: &TraitImplHeader,
|
||||
) -> &'hir hir::TraitImplHeader<'hir> {
|
||||
let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } =
|
||||
*trait_impl_header;
|
||||
let constness = self.lower_constness(constness);
|
||||
let safety = self.lower_safety(safety, hir::Safety::Safe);
|
||||
let polarity = match polarity {
|
||||
ImplPolarity::Positive => ImplPolarity::Positive,
|
||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
|
||||
};
|
||||
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
|
||||
// to not cause an assertion failure inside the `lower_defaultness` function.
|
||||
let has_val = true;
|
||||
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
asyncness: BoundAsyncness::Normal,
|
||||
// we don't use this in bound lowering
|
||||
polarity: BoundPolarity::Positive,
|
||||
};
|
||||
let trait_ref = self.lower_trait_ref(
|
||||
modifiers,
|
||||
trait_ref,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
);
|
||||
|
||||
self.arena.alloc(hir::TraitImplHeader {
|
||||
constness,
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
defaultness_span,
|
||||
trait_ref,
|
||||
})
|
||||
}
|
||||
|
||||
fn lower_impl_item(
|
||||
&mut self,
|
||||
i: &AssocItem,
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ enum RelaxedBoundPolicy<'a> {
|
|||
enum RelaxedBoundForbiddenReason {
|
||||
TraitObjectTy,
|
||||
SuperTrait,
|
||||
AssocTyBounds,
|
||||
LateBoundVarsInScope,
|
||||
}
|
||||
|
||||
|
|
@ -1109,9 +1110,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
|
||||
} else {
|
||||
// FIXME(#135229): These should be forbidden!
|
||||
let bounds =
|
||||
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
|
||||
let bounds = self.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::AssocTyBounds),
|
||||
itctx,
|
||||
);
|
||||
hir::AssocItemConstraintKind::Bound { bounds }
|
||||
}
|
||||
}
|
||||
|
|
@ -1217,7 +1220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_path_ty(
|
||||
&mut self,
|
||||
t: &Ty,
|
||||
qself: &Option<ptr::P<QSelf>>,
|
||||
qself: &Option<Box<QSelf>>,
|
||||
path: &Path,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
|
|
@ -2124,7 +2127,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
diag.emit();
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
|
||||
RelaxedBoundForbiddenReason::AssocTyBounds
|
||||
| RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -154,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn lower_pat_tuple(
|
||||
&mut self,
|
||||
pats: &[P<Pat>],
|
||||
pats: &[Box<Pat>],
|
||||
ctx: &str,
|
||||
) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
|
||||
let mut elems = Vec::with_capacity(pats.len());
|
||||
|
|
@ -209,7 +208,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// When encountering `($binding_mode $ident @)? ..` (`slice`),
|
||||
/// this is interpreted as a sub-slice pattern semantically.
|
||||
/// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
|
||||
fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
|
||||
fn lower_pat_slice(&mut self, pats: &[Box<Pat>]) -> hir::PatKind<'hir> {
|
||||
let mut before = Vec::new();
|
||||
let mut after = Vec::new();
|
||||
let mut slice = None;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
pub(crate) fn lower_qpath(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
qself: &Option<ptr::P<QSelf>>,
|
||||
qself: &Option<Box<QSelf>>,
|
||||
p: &Path,
|
||||
param_mode: ParamMode,
|
||||
allow_return_type_notation: AllowReturnTypeNotation,
|
||||
|
|
|
|||
|
|
@ -175,11 +175,6 @@ ast_passes_generic_default_trailing = generic parameters with a default must be
|
|||
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||
.help = remove one of these features
|
||||
|
||||
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
||||
.because = {$annotation} because of this
|
||||
.type = inherent impl for this type
|
||||
.only_trait = only trait implementations may be annotated with {$annotation}
|
||||
|
||||
ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
|
||||
.suggestion = remove safe from this item
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ use std::str::FromStr;
|
|||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_abi::{CanonAbi, ExternAbi, InterruptKind};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list};
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust::{self, State};
|
||||
|
|
@ -719,7 +718,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
|
||||
fn deny_items(&self, trait_items: &[Box<AssocItem>], ident_span: Span) {
|
||||
if !trait_items.is_empty() {
|
||||
let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
|
||||
let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
|
||||
|
|
@ -955,13 +954,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
|
||||
match &item.kind {
|
||||
ItemKind::Impl(box Impl {
|
||||
safety,
|
||||
polarity,
|
||||
defaultness: _,
|
||||
constness,
|
||||
ItemKind::Impl(Impl {
|
||||
generics,
|
||||
of_trait: Some(t),
|
||||
of_trait:
|
||||
Some(box TraitImplHeader {
|
||||
safety,
|
||||
polarity,
|
||||
defaultness: _,
|
||||
constness,
|
||||
trait_ref: t,
|
||||
}),
|
||||
self_ty,
|
||||
items,
|
||||
}) => {
|
||||
|
|
@ -993,46 +995,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true });
|
||||
});
|
||||
}
|
||||
ItemKind::Impl(box Impl {
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
constness,
|
||||
generics,
|
||||
of_trait: None,
|
||||
self_ty,
|
||||
items,
|
||||
}) => {
|
||||
let error = |annotation_span, annotation, only_trait| errors::InherentImplCannot {
|
||||
span: self_ty.span,
|
||||
annotation_span,
|
||||
annotation,
|
||||
self_ty: self_ty.span,
|
||||
only_trait,
|
||||
};
|
||||
|
||||
ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items }) => {
|
||||
self.visit_attrs_vis(&item.attrs, &item.vis);
|
||||
self.visibility_not_permitted(
|
||||
&item.vis,
|
||||
errors::VisibilityNotPermittedNote::IndividualImplItems,
|
||||
);
|
||||
if let &Safety::Unsafe(span) = safety {
|
||||
self.dcx().emit_err(errors::InherentImplCannotUnsafe {
|
||||
span: self_ty.span,
|
||||
annotation_span: span,
|
||||
annotation: "unsafe",
|
||||
self_ty: self_ty.span,
|
||||
});
|
||||
}
|
||||
if let &ImplPolarity::Negative(span) = polarity {
|
||||
self.dcx().emit_err(error(span, "negative", false));
|
||||
}
|
||||
if let &Defaultness::Default(def_span) = defaultness {
|
||||
self.dcx().emit_err(error(def_span, "`default`", true));
|
||||
}
|
||||
if let &Const::Yes(span) = constness {
|
||||
self.dcx().emit_err(error(span, "`const`", true));
|
||||
}
|
||||
|
||||
self.with_tilde_const(Some(TildeConstReason::Impl { span: item.span }), |this| {
|
||||
this.visit_generics(generics)
|
||||
|
|
|
|||
|
|
@ -464,32 +464,6 @@ pub(crate) struct UnsafeNegativeImpl {
|
|||
pub r#unsafe: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_inherent_cannot_be)]
|
||||
pub(crate) struct InherentImplCannot<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(ast_passes_because)]
|
||||
pub annotation_span: Span,
|
||||
pub annotation: &'a str,
|
||||
#[label(ast_passes_type)]
|
||||
pub self_ty: Span,
|
||||
#[note(ast_passes_only_trait)]
|
||||
pub only_trait: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_inherent_cannot_be, code = E0197)]
|
||||
pub(crate) struct InherentImplCannotUnsafe<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(ast_passes_because)]
|
||||
pub annotation_span: Span,
|
||||
pub annotation: &'a str,
|
||||
#[label(ast_passes_type)]
|
||||
pub self_ty: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_unsafe_item)]
|
||||
pub(crate) struct UnsafeItem {
|
||||
|
|
|
|||
|
|
@ -217,18 +217,18 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
|
||||
if let &ast::ImplPolarity::Negative(span) = polarity {
|
||||
ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) => {
|
||||
if let ast::ImplPolarity::Negative(span) = of_trait.polarity {
|
||||
gate!(
|
||||
&self,
|
||||
negative_impls,
|
||||
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
|
||||
span.to(of_trait.trait_ref.path.span),
|
||||
"negative trait bounds are not fully implemented; \
|
||||
use marker types for now"
|
||||
);
|
||||
}
|
||||
|
||||
if let ast::Defaultness::Default(_) = defaultness {
|
||||
if let ast::Defaultness::Default(_) = of_trait.defaultness {
|
||||
gate!(&self, specialization, i.span, "specialization is unstable");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use std::borrow::Cow;
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::attr::AttrIdGenerator;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
|
||||
use rustc_ast::util::classify;
|
||||
|
|
@ -1178,7 +1177,7 @@ impl<'a> State<'a> {
|
|||
self.end(rb);
|
||||
}
|
||||
|
||||
fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
|
||||
fn commasep_exprs(&mut self, b: Breaks, exprs: &[Box<ast::Expr>]) {
|
||||
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e, FixupContext::default()), |e| e.span)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::fmt::Write;
|
|||
|
||||
use ast::{ForLoopKind, MatchKind};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
|
||||
|
|
@ -54,7 +53,7 @@ impl<'a> State<'a> {
|
|||
self.print_else(elseopt)
|
||||
}
|
||||
|
||||
fn print_call_post(&mut self, args: &[P<ast::Expr>]) {
|
||||
fn print_call_post(&mut self, args: &[Box<ast::Expr>]) {
|
||||
self.popen();
|
||||
self.commasep_exprs(Inconsistent, args);
|
||||
self.pclose()
|
||||
|
|
@ -111,7 +110,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
|
||||
fn print_expr_vec(&mut self, exprs: &[Box<ast::Expr>]) {
|
||||
let ib = self.ibox(INDENT_UNIT);
|
||||
self.word("[");
|
||||
self.commasep_exprs(Inconsistent, exprs);
|
||||
|
|
@ -149,7 +148,7 @@ impl<'a> State<'a> {
|
|||
|
||||
fn print_expr_struct(
|
||||
&mut self,
|
||||
qself: &Option<P<ast::QSelf>>,
|
||||
qself: &Option<Box<ast::QSelf>>,
|
||||
path: &ast::Path,
|
||||
fields: &[ast::ExprField],
|
||||
rest: &ast::StructRest,
|
||||
|
|
@ -204,7 +203,7 @@ impl<'a> State<'a> {
|
|||
self.word("}");
|
||||
}
|
||||
|
||||
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) {
|
||||
fn print_expr_tup(&mut self, exprs: &[Box<ast::Expr>]) {
|
||||
self.popen();
|
||||
self.commasep_exprs(Inconsistent, exprs);
|
||||
if exprs.len() == 1 {
|
||||
|
|
@ -213,7 +212,7 @@ impl<'a> State<'a> {
|
|||
self.pclose()
|
||||
}
|
||||
|
||||
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
||||
fn print_expr_call(&mut self, func: &ast::Expr, args: &[Box<ast::Expr>], fixup: FixupContext) {
|
||||
// Independent of parenthesization related to precedence, we must
|
||||
// parenthesize `func` if this is a statement context in which without
|
||||
// parentheses, a statement boundary would occur inside `func` or
|
||||
|
|
@ -247,7 +246,7 @@ impl<'a> State<'a> {
|
|||
&mut self,
|
||||
segment: &ast::PathSegment,
|
||||
receiver: &ast::Expr,
|
||||
base_args: &[P<ast::Expr>],
|
||||
base_args: &[Box<ast::Expr>],
|
||||
fixup: FixupContext,
|
||||
) {
|
||||
// The fixup here is different than in `print_expr_call` because
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use ast::StaticItem;
|
|||
use itertools::{Itertools, Position};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ModKind;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_span::Ident;
|
||||
|
||||
use crate::pp::BoxMarker;
|
||||
|
|
@ -309,39 +308,41 @@ impl<'a> State<'a> {
|
|||
let (cb, ib) = self.head(visibility_qualified(&item.vis, "union"));
|
||||
self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
|
||||
}
|
||||
ast::ItemKind::Impl(box ast::Impl {
|
||||
safety,
|
||||
polarity,
|
||||
defaultness,
|
||||
constness,
|
||||
generics,
|
||||
of_trait,
|
||||
self_ty,
|
||||
items,
|
||||
}) => {
|
||||
ast::ItemKind::Impl(ast::Impl { generics, of_trait, self_ty, items }) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_visibility(&item.vis);
|
||||
self.print_defaultness(*defaultness);
|
||||
self.print_safety(*safety);
|
||||
self.word("impl");
|
||||
|
||||
if generics.params.is_empty() {
|
||||
self.nbsp();
|
||||
} else {
|
||||
self.print_generic_params(&generics.params);
|
||||
self.space();
|
||||
}
|
||||
let impl_generics = |this: &mut Self| {
|
||||
this.word("impl");
|
||||
|
||||
self.print_constness(*constness);
|
||||
if generics.params.is_empty() {
|
||||
this.nbsp();
|
||||
} else {
|
||||
this.print_generic_params(&generics.params);
|
||||
this.space();
|
||||
}
|
||||
};
|
||||
|
||||
if let ast::ImplPolarity::Negative(_) = polarity {
|
||||
self.word("!");
|
||||
}
|
||||
|
||||
if let Some(t) = of_trait {
|
||||
self.print_trait_ref(t);
|
||||
if let Some(box of_trait) = of_trait {
|
||||
let ast::TraitImplHeader {
|
||||
defaultness,
|
||||
safety,
|
||||
constness,
|
||||
polarity,
|
||||
ref trait_ref,
|
||||
} = *of_trait;
|
||||
self.print_defaultness(defaultness);
|
||||
self.print_safety(safety);
|
||||
impl_generics(self);
|
||||
self.print_constness(constness);
|
||||
if let ast::ImplPolarity::Negative(_) = polarity {
|
||||
self.word("!");
|
||||
}
|
||||
self.print_trait_ref(trait_ref);
|
||||
self.space();
|
||||
self.word_space("for");
|
||||
} else {
|
||||
impl_generics(self);
|
||||
}
|
||||
|
||||
self.print_type(self_ty);
|
||||
|
|
@ -628,10 +629,10 @@ impl<'a> State<'a> {
|
|||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
vis: &ast::Visibility,
|
||||
qself: &Option<P<ast::QSelf>>,
|
||||
qself: &Option<Box<ast::QSelf>>,
|
||||
path: &ast::Path,
|
||||
kind: DelegationKind<'_>,
|
||||
body: &Option<P<ast::Block>>,
|
||||
body: &Option<Box<ast::Block>>,
|
||||
) {
|
||||
let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
|
||||
self.print_visibility(vis);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ attr_parsing_unknown_version_literal =
|
|||
attr_parsing_unrecognized_repr_hint =
|
||||
unrecognized representation hint
|
||||
.help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
|
||||
.note = for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
|
||||
|
||||
attr_parsing_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
|
|||
type Item = (Symbol, Span);
|
||||
const CONVERT: ConvertFn<Self::Item> =
|
||||
|items, span| AttributeKind::AllowInternalUnstable(items, span);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -32,7 +32,7 @@ impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
|
|||
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
|
||||
type Item = (Symbol, Span);
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -53,7 +53,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
|||
type Item = Symbol;
|
||||
const CONVERT: ConvertFn<Self::Item> =
|
||||
|items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ use crate::{
|
|||
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
|
||||
};
|
||||
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(List: "predicate");
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["predicate"],
|
||||
"https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute"
|
||||
);
|
||||
|
||||
pub fn parse_cfg_attr<'c, S: Stage>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
|
|||
const PATH: &[Symbol] = &[sym::optimize];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(list) = args.list() else {
|
||||
|
|
@ -253,7 +253,7 @@ pub(crate) struct UsedParser {
|
|||
impl<S: Stage> AttributeParser<S> for UsedParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::used],
|
||||
template!(Word, List: "compiler|linker"),
|
||||
template!(Word, List: &["compiler", "linker"]),
|
||||
|group: &mut Self, cx, args| {
|
||||
let used_by = match args {
|
||||
ArgParser::NoArgs => UsedBy::Linker,
|
||||
|
|
@ -327,7 +327,7 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
|
|||
type Item = (Symbol, Span);
|
||||
const PATH: &[Symbol] = &[sym::target_feature];
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature(items, span);
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "enable = \"feat1, feat2\"");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub(crate) struct ConfusablesParser {
|
|||
impl<S: Stage> AttributeParser<S> for ConfusablesParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::rustc_confusables],
|
||||
template!(List: r#""name1", "name2", ..."#),
|
||||
template!(List: &[r#""name1", "name2", ..."#]),
|
||||
|this, cx, args| {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word,
|
||||
List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
|
||||
List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#],
|
||||
NameValueStr: "reason"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
|
|||
const PATH: &'static [Symbol] = &[sym::inline];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "always|never");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word,
|
||||
List: &["always", "never"],
|
||||
"https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
match args {
|
||||
|
|
@ -59,7 +63,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
|
|||
const PATH: &'static [Symbol] = &[sym::rustc_force_inline];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "reason", NameValueStr: "reason");
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let reason = match args {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
|
|||
const PATH: &[Symbol] = &[sym::link_name];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
NameValueStr: "name",
|
||||
"https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
|
|
@ -38,7 +41,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
|
|||
const PATH: &[Symbol] = &[sym::link_section];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
NameValueStr: "name",
|
||||
"https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
|
|
@ -94,7 +100,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
|
|||
const PATH: &[Symbol] = &[sym::link_ordinal];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "ordinal");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["ordinal"],
|
||||
"https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ordinal = parse_single_integer(cx, args)?;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ pub(crate) struct MacroUseParser {
|
|||
first_span: Option<Span>,
|
||||
}
|
||||
|
||||
const MACRO_USE_TEMPLATE: AttributeTemplate = template!(Word, List: "name1, name2, ...");
|
||||
const MACRO_USE_TEMPLATE: AttributeTemplate = template!(
|
||||
Word, List: &["name1, name2, ..."],
|
||||
"https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"
|
||||
);
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for MacroUseParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
|
|
@ -113,3 +116,11 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
|
|||
Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AllowInternalUnsafeParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
|
||||
const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
|
|||
const PATH: &[Symbol] = &[sym::must_use];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word, NameValueStr: "reason",
|
||||
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::MustUse {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ impl<S: Stage> SingleAttributeParser<S> for PathParser {
|
|||
const PATH: &[Symbol] = &[sym::path];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
NameValueStr: "file",
|
||||
"https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
|
|||
const PATH: &[Symbol] = &[sym::proc_macro_derive];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["TraitName", "TraitName, attributes(name1, name2, ...)"],
|
||||
"https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?;
|
||||
|
|
@ -47,7 +49,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
|
|||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
|
||||
template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
|
|||
const CONVERT: ConvertFn<Self::Item> =
|
||||
|items, first_span| AttributeKind::Repr { reprs: items, first_span };
|
||||
// FIXME(jdonszelmann): never used
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: "C | Rust | align(...) | packed(...) | <integer type> | transparent");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["C", "Rust", "transparent", "align(...)", "packed(...)", "<integer type>"],
|
||||
"https://doc.rust-lang.org/reference/type-layout.html#representations"
|
||||
);
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -275,7 +277,7 @@ pub(crate) struct AlignParser(Option<(Align, Span)>);
|
|||
|
||||
impl AlignParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_align];
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "<alignment in bytes>");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["<alignment in bytes>"]);
|
||||
|
||||
fn parse<'c, S: Stage>(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
|
|||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "start");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_single_integer(cx, args)
|
||||
|
|
@ -26,7 +26,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
|
|||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "end");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
parse_single_integer(cx, args)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
|
|||
const ATTRIBUTES: AcceptMapping<Self, S> = &[
|
||||
(
|
||||
&[sym::stable],
|
||||
template!(List: r#"feature = "name", since = "version""#),
|
||||
template!(List: &[r#"feature = "name", since = "version""#]),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
|
|
@ -60,7 +60,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
|
|||
),
|
||||
(
|
||||
&[sym::unstable],
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
|
||||
template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
|
|
@ -131,7 +131,7 @@ pub(crate) struct BodyStabilityParser {
|
|||
impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::rustc_default_body_unstable],
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
|
||||
template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if this.stability.is_some() {
|
||||
|
|
@ -177,29 +177,37 @@ impl ConstStabilityParser {
|
|||
|
||||
impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[
|
||||
(&[sym::rustc_const_stable], template!(List: r#"feature = "name""#), |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
(
|
||||
&[sym::rustc_const_stable],
|
||||
template!(List: &[r#"feature = "name""#]),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_stability(cx, args)
|
||||
{
|
||||
this.stability = Some((
|
||||
PartialConstStability { level, feature, promotable: false },
|
||||
cx.attr_span,
|
||||
));
|
||||
}
|
||||
}),
|
||||
(&[sym::rustc_const_unstable], template!(List: r#"feature = "name""#), |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_unstability(cx, args)
|
||||
{
|
||||
this.stability = Some((
|
||||
PartialConstStability { level, feature, promotable: false },
|
||||
cx.attr_span,
|
||||
));
|
||||
}
|
||||
}),
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_stability(cx, args)
|
||||
{
|
||||
this.stability = Some((
|
||||
PartialConstStability { level, feature, promotable: false },
|
||||
cx.attr_span,
|
||||
));
|
||||
}
|
||||
},
|
||||
),
|
||||
(
|
||||
&[sym::rustc_const_unstable],
|
||||
template!(List: &[r#"feature = "name""#]),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_unstability(cx, args)
|
||||
{
|
||||
this.stability = Some((
|
||||
PartialConstStability { level, feature, promotable: false },
|
||||
cx.attr_span,
|
||||
));
|
||||
}
|
||||
},
|
||||
),
|
||||
(&[sym::rustc_promotable], template!(Word), |this, cx, _| {
|
||||
reject_outside_std!(cx);
|
||||
this.promotable = true;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
|
|||
const PATH: &[Symbol] = &[sym::ignore];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word, NameValueStr: "reason",
|
||||
"https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::Ignore {
|
||||
|
|
@ -51,8 +54,10 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
|
|||
const PATH: &[Symbol] = &[sym::should_panic];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason");
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word, List: &[r#"expected = "reason""#], NameValueStr: "reason",
|
||||
"https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::ShouldPanic {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
|||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let mut array = false;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
|||
cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
|
||||
});
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(NameValueStr: "transparent|semitransparent|opaque");
|
||||
template!(NameValueStr: ["transparent", "semitransparent", "opaque"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(nv) = args.name_value() else {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ use crate::attributes::lint_helpers::{
|
|||
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
|
||||
};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser};
|
||||
use crate::attributes::macro_attrs::{
|
||||
AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
|
||||
};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
use crate::attributes::non_exhaustive::NonExhaustiveParser;
|
||||
|
|
@ -178,6 +180,7 @@ attribute_parsers!(
|
|||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TransparencyParser>,
|
||||
Single<WithoutArgs<AllowIncoherentImplParser>>,
|
||||
Single<WithoutArgs<AllowInternalUnsafeParser>>,
|
||||
Single<WithoutArgs<AsPtrParser>>,
|
||||
Single<WithoutArgs<AutomaticallyDerivedParser>>,
|
||||
Single<WithoutArgs<CoherenceIsCoreParser>>,
|
||||
|
|
|
|||
|
|
@ -498,6 +498,7 @@ pub(crate) struct ReprIdent {
|
|||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unrecognized_repr_hint, code = E0552)]
|
||||
#[help]
|
||||
#[note]
|
||||
pub(crate) struct UnrecognizedReprHint {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -690,6 +691,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(link) = self.template.docs {
|
||||
diag.note(format!("for more information, visit <{link}>"));
|
||||
}
|
||||
let suggestions = self.template.suggestions(false, &name);
|
||||
diag.span_suggestions(
|
||||
self.attr_span,
|
||||
|
|
|
|||
|
|
@ -410,18 +410,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
|
||||
let (def_id, call_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
|
||||
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
|
||||
{
|
||||
let def_id = typeck.type_dependent_def_id(parent_expr.hir_id);
|
||||
(def_id, Some(parent_expr.hir_id), args, 1)
|
||||
(def_id, args, 1)
|
||||
} else if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
|
||||
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
|
||||
{
|
||||
(Some(*def_id), Some(call.hir_id), args, 0)
|
||||
(Some(*def_id), args, 0)
|
||||
} else {
|
||||
(None, None, &[][..], 0)
|
||||
(None, &[][..], 0)
|
||||
};
|
||||
let ty = place.ty(self.body, self.infcx.tcx).ty;
|
||||
|
||||
|
|
@ -459,11 +459,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
// If the moved place is used generically by the callee and a reference to it
|
||||
// would still satisfy any bounds on its type, suggest borrowing.
|
||||
if let Some(¶m) = arg_param
|
||||
&& let Some(generic_args) = call_id.and_then(|id| typeck.node_args_opt(id))
|
||||
&& let hir::Node::Expr(call_expr) = parent
|
||||
&& let Some(ref_mutability) = self.suggest_borrow_generic_arg(
|
||||
err,
|
||||
typeck,
|
||||
call_expr,
|
||||
def_id,
|
||||
generic_args,
|
||||
param,
|
||||
moved_place,
|
||||
pos + offset,
|
||||
|
|
@ -627,8 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
fn suggest_borrow_generic_arg(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
typeck: &ty::TypeckResults<'tcx>,
|
||||
call_expr: &hir::Expr<'tcx>,
|
||||
callee_did: DefId,
|
||||
generic_args: ty::GenericArgsRef<'tcx>,
|
||||
param: ty::ParamTy,
|
||||
moved_place: PlaceRef<'tcx>,
|
||||
moved_arg_pos: usize,
|
||||
|
|
@ -639,6 +641,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
|
||||
let clauses = tcx.predicates_of(callee_did);
|
||||
|
||||
let generic_args = match call_expr.kind {
|
||||
// For method calls, generic arguments are attached to the call node.
|
||||
hir::ExprKind::MethodCall(..) => typeck.node_args_opt(call_expr.hir_id)?,
|
||||
// For normal calls, generic arguments are in the callee's type.
|
||||
// This diagnostic is only run for `FnDef` callees.
|
||||
hir::ExprKind::Call(callee, _)
|
||||
if let &ty::FnDef(_, args) = typeck.node_type(callee.hir_id).kind() =>
|
||||
{
|
||||
args
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// First, is there at least one method on one of `param`'s trait bounds?
|
||||
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
|
||||
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ mod conflict_errors;
|
|||
mod explain_borrow;
|
||||
mod move_errors;
|
||||
mod mutability_errors;
|
||||
mod opaque_suggestions;
|
||||
mod opaque_types;
|
||||
mod region_errors;
|
||||
|
||||
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use rustc_middle::bug;
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::{BytePos, DUMMY_SP, ExpnKind, MacroKind, Span};
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::debug;
|
||||
|
|
@ -507,12 +508,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
);
|
||||
|
||||
let closure_span = tcx.def_span(def_id);
|
||||
|
||||
self.cannot_move_out_of(span, &place_description)
|
||||
.with_span_label(upvar_span, "captured outer variable")
|
||||
.with_span_label(
|
||||
closure_span,
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
)
|
||||
.with_span_help(
|
||||
self.get_closure_bound_clause_span(*def_id),
|
||||
"`Fn` and `FnMut` closures require captured values to be able to be \
|
||||
consumed multiple times, but an `FnOnce` consume them only once",
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let source = self.borrowed_content_source(deref_base);
|
||||
|
|
@ -561,6 +568,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
err
|
||||
}
|
||||
|
||||
fn get_closure_bound_clause_span(&self, def_id: DefId) -> Span {
|
||||
let tcx = self.infcx.tcx;
|
||||
let typeck_result = tcx.typeck(self.mir_def_id());
|
||||
// Check whether the closure is an argument to a call, if so,
|
||||
// get the instantiated where-bounds of that call.
|
||||
let closure_hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
|
||||
let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return DUMMY_SP };
|
||||
|
||||
let predicates = match parent.kind {
|
||||
hir::ExprKind::Call(callee, _) => {
|
||||
let Some(ty) = typeck_result.node_type_opt(callee.hir_id) else { return DUMMY_SP };
|
||||
let ty::FnDef(fn_def_id, args) = ty.kind() else { return DUMMY_SP };
|
||||
tcx.predicates_of(fn_def_id).instantiate(tcx, args)
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => {
|
||||
let Some((_, method)) = typeck_result.type_dependent_def(parent.hir_id) else {
|
||||
return DUMMY_SP;
|
||||
};
|
||||
let args = typeck_result.node_args(parent.hir_id);
|
||||
tcx.predicates_of(method).instantiate(tcx, args)
|
||||
}
|
||||
_ => return DUMMY_SP,
|
||||
};
|
||||
|
||||
// Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`.
|
||||
for (pred, span) in predicates.predicates.iter().zip(predicates.spans.iter()) {
|
||||
if let Some(clause) = pred.as_trait_clause()
|
||||
&& let ty::Closure(clause_closure_def_id, _) = clause.self_ty().skip_binder().kind()
|
||||
&& *clause_closure_def_id == def_id
|
||||
&& (tcx.lang_items().fn_mut_trait() == Some(clause.def_id())
|
||||
|| tcx.lang_items().fn_trait() == Some(clause.def_id()))
|
||||
{
|
||||
// Found `<TyOfCapturingClosure as FnMut>`
|
||||
// We point at the `Fn()` or `FnMut()` bound that coerced the closure, which
|
||||
// could be changed to `FnOnce()` to avoid the move error.
|
||||
return *span;
|
||||
}
|
||||
}
|
||||
DUMMY_SP
|
||||
}
|
||||
|
||||
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
|
||||
match error {
|
||||
GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,28 @@ use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;
|
|||
use crate::MirBorrowckCtxt;
|
||||
use crate::borrow_set::BorrowData;
|
||||
use crate::consumers::RegionInferenceContext;
|
||||
use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
|
||||
use crate::type_check::Locations;
|
||||
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
pub(crate) fn report_opaque_type_errors(&mut self, errors: Vec<DeferredOpaqueTypeError<'tcx>>) {
|
||||
if errors.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut guar = None;
|
||||
for error in errors {
|
||||
guar = Some(match error {
|
||||
DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err) => err.report(self.infcx),
|
||||
DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(err) => {
|
||||
self.infcx.dcx().emit_err(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
let guar = guar.unwrap();
|
||||
self.root_cx.set_tainted_by_errors(guar);
|
||||
self.infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
/// Try to note when an opaque is involved in a borrowck error and that
|
||||
/// opaque captures lifetimes due to edition 2024.
|
||||
// FIXME: This code is otherwise somewhat general, and could easily be adapted
|
||||
|
|
@ -92,9 +92,6 @@ impl<'tcx> RegionErrors<'tcx> {
|
|||
) -> impl Iterator<Item = (RegionErrorKind<'tcx>, ErrorGuaranteed)> {
|
||||
self.0.into_iter()
|
||||
}
|
||||
pub(crate) fn has_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
self.0.get(0).map(|x| x.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RegionErrors<'_> {
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ fn region_definitions<'tcx>(
|
|||
for info in var_infos.iter() {
|
||||
let origin = match info.origin {
|
||||
RegionVariableOrigin::Nll(origin) => origin,
|
||||
_ => NllRegionVariableOrigin::Existential { from_forall: false },
|
||||
_ => NllRegionVariableOrigin::Existential { name: None },
|
||||
};
|
||||
|
||||
let definition = RegionDefinition { origin, universe: info.universe, external_name: None };
|
||||
|
|
@ -216,22 +216,11 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
|
|||
placeholder_index_to_region: _,
|
||||
liveness_constraints,
|
||||
mut outlives_constraints,
|
||||
mut member_constraints,
|
||||
member_constraints,
|
||||
universe_causes,
|
||||
type_tests,
|
||||
} = constraints;
|
||||
|
||||
if let Some(guar) = universal_regions.tainted_by_errors() {
|
||||
debug!("Universal regions tainted by errors; removing constraints!");
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
|
||||
// outlives bounds that we may end up checking.
|
||||
outlives_constraints = Default::default();
|
||||
member_constraints = Default::default();
|
||||
|
||||
// Also taint the entire scope.
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let compute_sccs =
|
||||
|constraints: &OutlivesConstraintSet<'tcx>,
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
polonius_context,
|
||||
);
|
||||
|
||||
regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
|
||||
let opaque_type_errors = regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
|
||||
|
||||
// Dump MIR results into a file, if that is enabled. This lets us
|
||||
// write unit-tests, as well as helping with debugging.
|
||||
|
|
@ -471,7 +471,11 @@ fn do_mir_borrowck<'tcx>(
|
|||
};
|
||||
|
||||
// Compute and report region errors, if any.
|
||||
mbcx.report_region_errors(nll_errors);
|
||||
if nll_errors.is_empty() {
|
||||
mbcx.report_opaque_type_errors(opaque_type_errors);
|
||||
} else {
|
||||
mbcx.report_region_errors(nll_errors);
|
||||
}
|
||||
|
||||
let (mut flow_analysis, flow_entry_states) =
|
||||
get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx);
|
||||
|
|
|
|||
|
|
@ -148,11 +148,6 @@ pub(crate) fn compute_regions<'tcx>(
|
|||
let (closure_region_requirements, nll_errors) =
|
||||
regioncx.solve(infcx, body, polonius_output.clone());
|
||||
|
||||
if let Some(guar) = nll_errors.has_errors() {
|
||||
// Suppress unhelpful extra errors in `infer_opaque_types`.
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
NllOutput {
|
||||
regioncx,
|
||||
polonius_input: polonius_facts.map(Box::new),
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ use rustc_mir_dataflow::points::PointIndex;
|
|||
///
|
||||
/// This models two sources of constraints:
|
||||
/// - constraints that traverse the subsets between regions at a given point, `a@p: b@p`. These
|
||||
/// depend on typeck constraints generated via assignments, calls, etc. (In practice there are
|
||||
/// subtleties where a statement's effect only starts being visible at the successor point, via
|
||||
/// the "result" of that statement).
|
||||
/// depend on typeck constraints generated via assignments, calls, etc.
|
||||
/// - constraints that traverse the CFG via the same region, `a@p: a@q`, where `p` is a predecessor
|
||||
/// of `q`. These depend on the liveness of the regions at these points, as well as their
|
||||
/// variance.
|
||||
|
|
|
|||
|
|
@ -184,22 +184,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<A, B, C, D> FactRow for (A, B, C, D)
|
||||
where
|
||||
A: FactCell,
|
||||
B: FactCell,
|
||||
C: FactCell,
|
||||
D: FactCell,
|
||||
{
|
||||
fn write(
|
||||
&self,
|
||||
out: &mut dyn Write,
|
||||
location_table: &PoloniusLocationTable,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
|
||||
}
|
||||
}
|
||||
|
||||
fn write_row(
|
||||
out: &mut dyn Write,
|
||||
location_table: &PoloniusLocationTable,
|
||||
|
|
|
|||
|
|
@ -105,22 +105,14 @@ fn propagate_loans_between_points(
|
|||
});
|
||||
}
|
||||
|
||||
let Some(current_live_regions) = live_regions.row(current_point) else {
|
||||
// There are no constraints to add: there are no live regions at the current point.
|
||||
return;
|
||||
};
|
||||
let Some(next_live_regions) = live_regions.row(next_point) else {
|
||||
// There are no constraints to add: there are no live regions at the next point.
|
||||
return;
|
||||
};
|
||||
|
||||
for region in next_live_regions.iter() {
|
||||
if !current_live_regions.contains(region) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// `region` is indeed live at both points, add a constraint between them, according to
|
||||
// variance.
|
||||
// `region` could be live at the current point, and is live at the next point: add a
|
||||
// constraint between them, according to variance.
|
||||
if let Some(&direction) = live_region_variances.get(®ion) {
|
||||
add_liveness_constraint(
|
||||
region,
|
||||
|
|
|
|||
|
|
@ -1,27 +1,18 @@
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{
|
||||
Body, Local, Location, Place, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
use rustc_middle::ty::RegionVid;
|
||||
use rustc_mir_dataflow::points::PointIndex;
|
||||
|
||||
use super::{LiveLoans, LocalizedOutlivesConstraintSet};
|
||||
use crate::BorrowSet;
|
||||
use crate::constraints::OutlivesConstraint;
|
||||
use crate::dataflow::BorrowIndex;
|
||||
use crate::region_infer::values::LivenessValues;
|
||||
use crate::type_check::Locations;
|
||||
use crate::{BorrowSet, PlaceConflictBias, places_conflict};
|
||||
|
||||
/// Compute loan reachability, stop at kills, and trace loan liveness throughout the CFG, by
|
||||
/// Compute loan reachability to approximately trace loan liveness throughout the CFG, by
|
||||
/// traversing the full graph of constraints that combines:
|
||||
/// - the localized constraints (the physical edges),
|
||||
/// - with the constraints that hold at all points (the logical edges).
|
||||
pub(super) fn compute_loan_liveness<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
liveness: &LivenessValues,
|
||||
outlives_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
|
|
@ -29,11 +20,6 @@ pub(super) fn compute_loan_liveness<'tcx>(
|
|||
) -> LiveLoans {
|
||||
let mut live_loans = LiveLoans::new(borrow_set.len());
|
||||
|
||||
// FIXME: it may be preferable for kills to be encoded in the edges themselves, to simplify and
|
||||
// likely make traversal (and constraint generation) more efficient. We also display kills on
|
||||
// edges when visualizing the constraint graph anyways.
|
||||
let kills = collect_kills(body, tcx, borrow_set);
|
||||
|
||||
// Create the full graph with the physical edges we've localized earlier, and the logical edges
|
||||
// of constraints that hold at all points.
|
||||
let logical_constraints =
|
||||
|
|
@ -59,15 +45,15 @@ pub(super) fn compute_loan_liveness<'tcx>(
|
|||
continue;
|
||||
}
|
||||
|
||||
// Record the loan as being live on entry to this point.
|
||||
live_loans.insert(node.point, loan_idx);
|
||||
|
||||
// Here, we have a conundrum. There's currently a weakness in our theory, in that
|
||||
// we're using a single notion of reachability to represent what used to be _two_
|
||||
// different transitive closures. It didn't seem impactful when coming up with the
|
||||
// single-graph and reachability through space (regions) + time (CFG) concepts, but in
|
||||
// practice the combination of time-traveling with kills is more impactful than
|
||||
// initially anticipated.
|
||||
// Record the loan as being live on entry to this point if it reaches a live region
|
||||
// there.
|
||||
//
|
||||
// This is an approximation of liveness (which is the thing we want), in that we're
|
||||
// using a single notion of reachability to represent what used to be _two_ different
|
||||
// transitive closures. It didn't seem impactful when coming up with the single-graph
|
||||
// and reachability through space (regions) + time (CFG) concepts, but in practice the
|
||||
// combination of time-traveling with kills is more impactful than initially
|
||||
// anticipated.
|
||||
//
|
||||
// Kills should prevent a loan from reaching its successor points in the CFG, but not
|
||||
// while time-traveling: we're not actually at that CFG point, but looking for
|
||||
|
|
@ -92,40 +78,20 @@ pub(super) fn compute_loan_liveness<'tcx>(
|
|||
// two-step traversal described above: only kills encountered on exit via a backward
|
||||
// edge are ignored.
|
||||
//
|
||||
// In our test suite, there are a couple of cases where kills are encountered while
|
||||
// time-traveling, however as far as we can tell, always in cases where they would be
|
||||
// unreachable. We have reason to believe that this is a property of the single-graph
|
||||
// approach (but haven't proved it yet):
|
||||
// - reachable kills while time-traveling would also be encountered via regular
|
||||
// traversal
|
||||
// - it makes _some_ sense to ignore unreachable kills, but subtleties around dead code
|
||||
// in general need to be better thought through (like they were for NLLs).
|
||||
// - ignoring kills is a conservative approximation: the loan is still live and could
|
||||
// cause false positive errors at another place access. Soundness issues in this
|
||||
// domain should look more like the absence of reachability instead.
|
||||
// This version of the analysis, however, is enough in practice to pass the tests that
|
||||
// we care about and NLLs reject, without regressions on crater, and is an actionable
|
||||
// subset of the full analysis. It also naturally points to areas of improvement that we
|
||||
// wish to explore later, namely handling kills appropriately during traversal, instead
|
||||
// of continuing traversal to all the reachable nodes.
|
||||
//
|
||||
// This is enough in practice to pass tests, and therefore is what we have implemented
|
||||
// for now.
|
||||
//
|
||||
// FIXME: all of the above. Analyze potential unsoundness, possibly in concert with a
|
||||
// borrowck implementation in a-mir-formality, fuzzing, or manually crafting
|
||||
// counter-examples.
|
||||
// FIXME: analyze potential unsoundness, possibly in concert with a borrowck
|
||||
// implementation in a-mir-formality, fuzzing, or manually crafting counter-examples.
|
||||
|
||||
// Continuing traversal will depend on whether the loan is killed at this point, and
|
||||
// whether we're time-traveling.
|
||||
let current_location = liveness.location_from_point(node.point);
|
||||
let is_loan_killed =
|
||||
kills.get(¤t_location).is_some_and(|kills| kills.contains(&loan_idx));
|
||||
if liveness.is_live_at(node.region, liveness.location_from_point(node.point)) {
|
||||
live_loans.insert(node.point, loan_idx);
|
||||
}
|
||||
|
||||
for succ in graph.outgoing_edges(node) {
|
||||
// If the loan is killed at this point, it is killed _on exit_. But only during
|
||||
// forward traversal.
|
||||
if is_loan_killed {
|
||||
let destination = liveness.location_from_point(succ.point);
|
||||
if current_location.is_predecessor_of(destination, body) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stack.push(succ);
|
||||
}
|
||||
}
|
||||
|
|
@ -192,116 +158,3 @@ impl LocalizedConstraintGraph {
|
|||
physical_edges.chain(materialized_edges)
|
||||
}
|
||||
}
|
||||
|
||||
/// Traverses the MIR and collects kills.
|
||||
fn collect_kills<'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) -> BTreeMap<Location, BTreeSet<BorrowIndex>> {
|
||||
let mut collector = KillsCollector { borrow_set, tcx, body, kills: BTreeMap::default() };
|
||||
for (block, data) in body.basic_blocks.iter_enumerated() {
|
||||
collector.visit_basic_block_data(block, data);
|
||||
}
|
||||
collector.kills
|
||||
}
|
||||
|
||||
struct KillsCollector<'a, 'tcx> {
|
||||
body: &'a Body<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
|
||||
/// The set of loans killed at each location.
|
||||
kills: BTreeMap<Location, BTreeSet<BorrowIndex>>,
|
||||
}
|
||||
|
||||
// This visitor has a similar structure to the `Borrows` dataflow computation with respect to kills,
|
||||
// and the datalog polonius fact generation for the `loan_killed_at` relation.
|
||||
impl<'tcx> KillsCollector<'_, 'tcx> {
|
||||
/// Records the borrows on the specified place as `killed`. For example, when assigning to a
|
||||
/// local, or on a call's return destination.
|
||||
fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
|
||||
// For the reasons described in graph traversal, we also filter out kills
|
||||
// unreachable from the loan's introduction point, as they would stop traversal when
|
||||
// e.g. checking for reachability in the subset graph through invariance constraints
|
||||
// higher up.
|
||||
let filter_unreachable_kills = |loan| {
|
||||
let introduction = self.borrow_set[loan].reserve_location;
|
||||
let reachable = introduction.is_predecessor_of(location, self.body);
|
||||
reachable
|
||||
};
|
||||
|
||||
let other_borrows_of_local = self
|
||||
.borrow_set
|
||||
.local_map
|
||||
.get(&place.local)
|
||||
.into_iter()
|
||||
.flat_map(|bs| bs.iter())
|
||||
.copied();
|
||||
|
||||
// If the borrowed place is a local with no projections, all other borrows of this
|
||||
// local must conflict. This is purely an optimization so we don't have to call
|
||||
// `places_conflict` for every borrow.
|
||||
if place.projection.is_empty() {
|
||||
if !self.body.local_decls[place.local].is_ref_to_static() {
|
||||
self.kills
|
||||
.entry(location)
|
||||
.or_default()
|
||||
.extend(other_borrows_of_local.filter(|&loan| filter_unreachable_kills(loan)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
|
||||
// pair of array indices are not equal, so that when `places_conflict` returns true, we
|
||||
// will be assured that two places being compared definitely denotes the same sets of
|
||||
// locations.
|
||||
let definitely_conflicting_borrows = other_borrows_of_local
|
||||
.filter(|&i| {
|
||||
places_conflict(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.borrow_set[i].borrowed_place,
|
||||
place,
|
||||
PlaceConflictBias::NoOverlap,
|
||||
)
|
||||
})
|
||||
.filter(|&loan| filter_unreachable_kills(loan));
|
||||
|
||||
self.kills.entry(location).or_default().extend(definitely_conflicting_borrows);
|
||||
}
|
||||
|
||||
/// Records the borrows on the specified local as `killed`.
|
||||
fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
|
||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||
self.kills.entry(location).or_default().extend(borrow_indices.iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for KillsCollector<'_, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
// Make sure there are no remaining borrows for locals that have gone out of scope.
|
||||
if let StatementKind::StorageDead(local) = statement.kind {
|
||||
self.record_killed_borrows_for_local(local, location);
|
||||
}
|
||||
|
||||
self.super_statement(statement, location);
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
// When we see `X = ...`, then kill borrows of `(*X).foo` and so forth.
|
||||
self.record_killed_borrows_for_place(*place, location);
|
||||
self.super_assign(place, rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
// A `Call` terminator's return value can be a local which has borrows, so we need to record
|
||||
// those as killed as well.
|
||||
if let TerminatorKind::Call { destination, .. } = terminator.kind {
|
||||
self.record_killed_borrows_for_place(destination, location);
|
||||
}
|
||||
|
||||
self.super_terminator(terminator, location);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,8 +146,8 @@ impl PoloniusContext {
|
|||
/// - converting NLL typeck constraints to be localized
|
||||
/// - encoding liveness constraints
|
||||
///
|
||||
/// Then, this graph is traversed, and combined with kills, reachability is recorded as loan
|
||||
/// liveness, to be used by the loan scope and active loans computations.
|
||||
/// Then, this graph is traversed, reachability is recorded as loan liveness, to be used by the
|
||||
/// loan scope and active loans computations.
|
||||
///
|
||||
/// The constraint data will be used to compute errors and diagnostics.
|
||||
pub(crate) fn compute_loan_liveness<'tcx>(
|
||||
|
|
@ -182,8 +182,6 @@ impl PoloniusContext {
|
|||
// Now that we have a complete graph, we can compute reachability to trace the liveness of
|
||||
// loans for the next step in the chain, the NLL loan scope and active loans computations.
|
||||
let live_loans = compute_loan_liveness(
|
||||
tcx,
|
||||
body,
|
||||
regioncx.liveness_constraints(),
|
||||
regioncx.outlives_constraints(),
|
||||
borrow_set,
|
||||
|
|
|
|||
|
|
@ -47,9 +47,7 @@ pub(super) fn convert_typeck_constraints<'tcx>(
|
|||
tcx,
|
||||
body,
|
||||
stmt,
|
||||
liveness,
|
||||
&outlives_constraint,
|
||||
location,
|
||||
point,
|
||||
universal_regions,
|
||||
)
|
||||
|
|
@ -78,9 +76,7 @@ fn localize_statement_constraint<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
stmt: &Statement<'tcx>,
|
||||
liveness: &LivenessValues,
|
||||
outlives_constraint: &OutlivesConstraint<'tcx>,
|
||||
current_location: Location,
|
||||
current_point: PointIndex,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
) -> LocalizedOutlivesConstraint {
|
||||
|
|
@ -98,8 +94,8 @@ fn localize_statement_constraint<'tcx>(
|
|||
// - and that should be impossible in MIR
|
||||
//
|
||||
// When we have a more complete implementation in the future, tested with crater, etc,
|
||||
// we can relax this to a debug assert instead, or remove it.
|
||||
assert!(
|
||||
// we can remove this assertion. It's a debug assert because it can be expensive.
|
||||
debug_assert!(
|
||||
{
|
||||
let mut lhs_regions = FxHashSet::default();
|
||||
tcx.for_each_free_region(lhs, |region| {
|
||||
|
|
@ -119,16 +115,8 @@ fn localize_statement_constraint<'tcx>(
|
|||
"there should be no common regions between the LHS and RHS of an assignment"
|
||||
);
|
||||
|
||||
// As mentioned earlier, we should be tracking these better upstream but: we want to
|
||||
// relate the types on entry to the type of the place on exit. That is, outlives
|
||||
// constraints on the RHS are on entry, and outlives constraints to/from the LHS are on
|
||||
// exit (i.e. on entry to the successor location).
|
||||
let lhs_ty = body.local_decls[lhs.local].ty;
|
||||
let successor_location = Location {
|
||||
block: current_location.block,
|
||||
statement_index: current_location.statement_index + 1,
|
||||
};
|
||||
let successor_point = liveness.point_from_location(successor_location);
|
||||
let successor_point = current_point;
|
||||
compute_constraint_direction(
|
||||
tcx,
|
||||
outlives_constraint,
|
||||
|
|
@ -195,6 +183,7 @@ fn localize_terminator_constraint<'tcx>(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For a given outlives constraint and CFG edge, returns the localized constraint with the
|
||||
/// appropriate `from`-`to` direction. This is computed according to whether the constraint flows to
|
||||
/// or from a free region in the given `value`, some kind of result for an effectful operation, like
|
||||
|
|
|
|||
|
|
@ -41,7 +41,22 @@ fn render_region_vid<'tcx>(
|
|||
"".to_string()
|
||||
};
|
||||
|
||||
format!("{:?}{universe_str}{external_name_str}", rvid)
|
||||
let extra_info = match regioncx.region_definition(rvid).origin {
|
||||
NllRegionVariableOrigin::FreeRegion => "".to_string(),
|
||||
NllRegionVariableOrigin::Placeholder(p) => match p.bound.kind {
|
||||
ty::BoundRegionKind::Named(def_id) => {
|
||||
format!(" (for<{}>)", tcx.item_name(def_id))
|
||||
}
|
||||
ty::BoundRegionKind::ClosureEnv | ty::BoundRegionKind::Anon => " (for<'_>)".to_string(),
|
||||
ty::BoundRegionKind::NamedAnon(_) => {
|
||||
bug!("only used for pretty printing")
|
||||
}
|
||||
},
|
||||
NllRegionVariableOrigin::Existential { name: Some(name), .. } => format!(" (ex<{name}>)"),
|
||||
NllRegionVariableOrigin::Existential { .. } => format!(" (ex<'_>)"),
|
||||
};
|
||||
|
||||
format!("{:?}{universe_str}{external_name_str}{extra_info}", rvid)
|
||||
}
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ use crate::{
|
|||
|
||||
mod dump_mir;
|
||||
mod graphviz;
|
||||
mod opaque_types;
|
||||
pub(crate) mod opaque_types;
|
||||
mod reverse_sccs;
|
||||
|
||||
pub(crate) mod values;
|
||||
|
|
@ -1939,10 +1939,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
//
|
||||
// and here we prefer to blame the source (the y = x statement).
|
||||
let blame_source = match from_region_origin {
|
||||
NllRegionVariableOrigin::FreeRegion
|
||||
| NllRegionVariableOrigin::Existential { from_forall: false } => true,
|
||||
NllRegionVariableOrigin::Placeholder(_)
|
||||
| NllRegionVariableOrigin::Existential { from_forall: true } => false,
|
||||
NllRegionVariableOrigin::FreeRegion => true,
|
||||
NllRegionVariableOrigin::Placeholder(_) => false,
|
||||
// `'existential: 'whatever` never results in a region error by itself.
|
||||
// We may always infer it to `'static` afterall. This means while an error
|
||||
// path may go through an existential, these existentials are never the
|
||||
// `from_region`.
|
||||
NllRegionVariableOrigin::Existential { name: _ } => {
|
||||
unreachable!("existentials can outlive everything")
|
||||
}
|
||||
};
|
||||
|
||||
// To pick a constraint to blame, we organize constraints by how interesting we expect them
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ use rustc_middle::ty::{
|
|||
TypeVisitableExt, fold_regions,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
|
||||
use rustc_trait_selection::opaque_types::{
|
||||
InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
|
||||
};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::RegionInferenceContext;
|
||||
|
|
@ -14,6 +16,11 @@ use crate::BorrowCheckRootCtxt;
|
|||
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||
use crate::universal_regions::RegionClassification;
|
||||
|
||||
pub(crate) enum DeferredOpaqueTypeError<'tcx> {
|
||||
InvalidOpaqueTypeArgs(InvalidOpaqueTypeArgs<'tcx>),
|
||||
LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Resolve any opaque types that were encountered while borrow checking
|
||||
/// this item. This is then used to get the type in the `type_of` query.
|
||||
|
|
@ -58,13 +65,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
///
|
||||
/// [rustc-dev-guide chapter]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||
#[instrument(level = "debug", skip(self, root_cx, infcx), ret)]
|
||||
#[instrument(level = "debug", skip(self, root_cx, infcx))]
|
||||
pub(crate) fn infer_opaque_types(
|
||||
&self,
|
||||
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) {
|
||||
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
|
||||
let mut errors = Vec::new();
|
||||
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
||||
FxIndexMap::default();
|
||||
|
||||
|
|
@ -124,8 +132,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
});
|
||||
debug!(?concrete_type);
|
||||
|
||||
let ty =
|
||||
infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
|
||||
let ty = match infcx
|
||||
.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type)
|
||||
{
|
||||
Ok(ty) => ty,
|
||||
Err(err) => {
|
||||
errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Sometimes, when the hidden type is an inference variable, it can happen that
|
||||
// the hidden type becomes the opaque type itself. In this case, this was an opaque
|
||||
|
|
@ -149,25 +164,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// non-region parameters. This is necessary because within the new solver we perform
|
||||
// various query operations modulo regions, and thus could unsoundly select some impls
|
||||
// that don't hold.
|
||||
if !ty.references_error()
|
||||
&& let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
|
||||
infcx.tcx.erase_regions(opaque_type_key),
|
||||
(opaque_type_key, concrete_type.span),
|
||||
)
|
||||
&& let Some((arg1, arg2)) = std::iter::zip(
|
||||
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
)
|
||||
.find(|(arg1, arg2)| arg1 != arg2)
|
||||
if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
|
||||
infcx.tcx.erase_regions(opaque_type_key),
|
||||
(opaque_type_key, concrete_type.span),
|
||||
) && let Some((arg1, arg2)) = std::iter::zip(
|
||||
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
)
|
||||
.find(|(arg1, arg2)| arg1 != arg2)
|
||||
{
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: arg1,
|
||||
prev: arg2,
|
||||
span: prev_span,
|
||||
prev_span: concrete_type.span,
|
||||
});
|
||||
errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
|
||||
LifetimeMismatchOpaqueParam {
|
||||
arg: arg1,
|
||||
prev: arg2,
|
||||
span: prev_span,
|
||||
prev_span: concrete_type.span,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
errors
|
||||
}
|
||||
|
||||
/// Map the regions in the type to named regions. This is similar to what
|
||||
|
|
@ -260,19 +277,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
if let Err(err) = check_opaque_type_parameter_valid(
|
||||
) -> Result<Ty<'tcx>, InvalidOpaqueTypeArgs<'tcx>> {
|
||||
check_opaque_type_parameter_valid(
|
||||
self,
|
||||
opaque_type_key,
|
||||
instantiated_ty.span,
|
||||
DefiningScopeKind::MirBorrowck,
|
||||
) {
|
||||
return Ty::new_error(self.tcx, err.report(self));
|
||||
}
|
||||
)?;
|
||||
|
||||
let definition_ty = instantiated_ty
|
||||
.remap_generic_params_to_declaration_params(
|
||||
|
|
@ -282,10 +293,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
)
|
||||
.ty;
|
||||
|
||||
if let Err(e) = definition_ty.error_reported() {
|
||||
return Ty::new_error(self.tcx, e);
|
||||
}
|
||||
|
||||
definition_ty
|
||||
definition_ty.error_reported()?;
|
||||
Ok(definition_ty)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
|
|||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
F: Fn() -> RegionCtxt,
|
||||
{
|
||||
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
|
||||
let origin = NllRegionVariableOrigin::Existential { name: None };
|
||||
fold_regions(self.infcx.tcx, value, |_region, _depth| {
|
||||
self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -182,6 +182,17 @@ pub(crate) fn type_check<'tcx>(
|
|||
)
|
||||
});
|
||||
|
||||
// In case type check encountered an error region, we suppress unhelpful extra
|
||||
// errors in by clearing out all outlives bounds that we may end up checking.
|
||||
if let Some(guar) = universal_region_relations.universal_regions.encountered_re_error() {
|
||||
debug!("encountered an error region; removing constraints!");
|
||||
constraints.outlives_constraints = Default::default();
|
||||
constraints.member_constraints = Default::default();
|
||||
constraints.type_tests = Default::default();
|
||||
root_cx.set_tainted_by_errors(guar);
|
||||
infcx.set_tainted_by_errors(guar);
|
||||
}
|
||||
|
||||
MirTypeckResults {
|
||||
constraints,
|
||||
universal_region_relations,
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
*ex_reg_var
|
||||
} else {
|
||||
let ex_reg_var =
|
||||
self.next_existential_region_var(true, br.kind.get_name(infcx.infcx.tcx));
|
||||
self.next_existential_region_var(br.kind.get_name(infcx.infcx.tcx));
|
||||
debug!(?ex_reg_var);
|
||||
reg_map.insert(br, ex_reg_var);
|
||||
|
||||
|
|
@ -244,17 +244,9 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn next_existential_region_var(
|
||||
&mut self,
|
||||
from_forall: bool,
|
||||
name: Option<Symbol>,
|
||||
) -> ty::Region<'tcx> {
|
||||
let origin = NllRegionVariableOrigin::Existential { from_forall };
|
||||
|
||||
let reg_var =
|
||||
self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name));
|
||||
|
||||
reg_var
|
||||
fn next_existential_region_var(&mut self, name: Option<Symbol>) -> ty::Region<'tcx> {
|
||||
let origin = NllRegionVariableOrigin::Existential { name };
|
||||
self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name))
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ struct UniversalRegionIndices<'tcx> {
|
|||
|
||||
/// Whether we've encountered an error region. If we have, cancel all
|
||||
/// outlives errors, as they are likely bogus.
|
||||
pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
|
||||
pub encountered_re_error: Cell<Option<ErrorGuaranteed>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
@ -442,8 +442,8 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||
self.fr_fn_body
|
||||
}
|
||||
|
||||
pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
self.indices.tainted_by_errors.get()
|
||||
pub(crate) fn encountered_re_error(&self) -> Option<ErrorGuaranteed> {
|
||||
self.indices.encountered_re_error.get()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -706,7 +706,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
UniversalRegionIndices {
|
||||
indices: global_mapping.chain(arg_mapping).collect(),
|
||||
fr_static,
|
||||
tainted_by_errors: Cell::new(None),
|
||||
encountered_re_error: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -916,7 +916,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
|||
match r.kind() {
|
||||
ty::ReVar(..) => r.as_var(),
|
||||
ty::ReError(guar) => {
|
||||
self.tainted_by_errors.set(Some(guar));
|
||||
self.encountered_re_error.set(Some(guar));
|
||||
// We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
|
||||
// `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
|
||||
// errors are being emitted and 2) it leaves the happy path unaffected.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{
|
||||
self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
|
||||
};
|
||||
|
|
@ -46,7 +45,7 @@ pub(crate) fn expand(
|
|||
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
} else {
|
||||
Annotatable::Item(const_item)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use lint::BuiltinLintDiag;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AsmMacro, token};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
|
|
@ -19,7 +18,7 @@ use crate::{errors, fluent_generated as fluent};
|
|||
|
||||
/// Validated assembly arguments, ready for macro expansion.
|
||||
struct ValidatedAsmArgs {
|
||||
pub templates: Vec<P<ast::Expr>>,
|
||||
pub templates: Vec<Box<ast::Expr>>,
|
||||
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
|
||||
named_args: FxIndexMap<Symbol, usize>,
|
||||
reg_args: GrowableBitSet<usize>,
|
||||
|
|
@ -600,9 +599,9 @@ pub(super) fn expand_asm<'cx>(
|
|||
return ExpandResult::Retry(());
|
||||
};
|
||||
let expr = match mac {
|
||||
Ok(inline_asm) => P(ast::Expr {
|
||||
Ok(inline_asm) => Box::new(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
||||
kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)),
|
||||
span: sp,
|
||||
attrs: ast::AttrVec::new(),
|
||||
tokens: None,
|
||||
|
|
@ -630,9 +629,9 @@ pub(super) fn expand_naked_asm<'cx>(
|
|||
return ExpandResult::Retry(());
|
||||
};
|
||||
let expr = match mac {
|
||||
Ok(inline_asm) => P(ast::Expr {
|
||||
Ok(inline_asm) => Box::new(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
||||
kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)),
|
||||
span: sp,
|
||||
attrs: ast::AttrVec::new(),
|
||||
tokens: None,
|
||||
|
|
@ -660,7 +659,7 @@ pub(super) fn expand_global_asm<'cx>(
|
|||
return ExpandResult::Retry(());
|
||||
};
|
||||
match mac {
|
||||
Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
|
||||
Ok(inline_asm) => MacEager::items(smallvec![Box::new(ast::Item {
|
||||
attrs: ast::AttrVec::new(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
mod context;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token};
|
||||
|
|
@ -55,9 +54,9 @@ pub(crate) fn expand_assert<'cx>(
|
|||
let expr = if let Some(tokens) = custom_message {
|
||||
let then = cx.expr(
|
||||
call_site_span,
|
||||
ExprKind::MacCall(P(MacCall {
|
||||
ExprKind::MacCall(Box::new(MacCall {
|
||||
path: panic_path(),
|
||||
args: P(DelimArgs {
|
||||
args: Box::new(DelimArgs {
|
||||
dspan: DelimSpan::from_single(call_site_span),
|
||||
delim: Delimiter::Parenthesis,
|
||||
tokens,
|
||||
|
|
@ -96,7 +95,7 @@ pub(crate) fn expand_assert<'cx>(
|
|||
}
|
||||
|
||||
struct Assert {
|
||||
cond_expr: P<Expr>,
|
||||
cond_expr: Box<Expr>,
|
||||
custom_message: Option<TokenStream>,
|
||||
}
|
||||
|
||||
|
|
@ -104,10 +103,10 @@ struct Assert {
|
|||
fn expr_if_not(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
cond: P<Expr>,
|
||||
then: P<Expr>,
|
||||
els: Option<P<Expr>>,
|
||||
) -> P<Expr> {
|
||||
cond: Box<Expr>,
|
||||
then: Box<Expr>,
|
||||
els: Option<Box<Expr>>,
|
||||
) -> Box<Expr> {
|
||||
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, IdentIsRaw};
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||
use rustc_ast::{
|
||||
|
|
@ -70,7 +69,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub(super) fn build(mut self, mut cond_expr: P<Expr>, panic_path: Path) -> P<Expr> {
|
||||
pub(super) fn build(mut self, mut cond_expr: Box<Expr>, panic_path: Path) -> Box<Expr> {
|
||||
let expr_str = pprust::expr_to_string(&cond_expr);
|
||||
self.manage_cond_expr(&mut cond_expr);
|
||||
let initial_imports = self.build_initial_imports();
|
||||
|
|
@ -129,7 +128,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
}
|
||||
|
||||
/// Takes the conditional expression of `assert!` and then wraps it inside `unlikely`
|
||||
fn build_unlikely(&self, cond_expr: P<Expr>) -> P<Expr> {
|
||||
fn build_unlikely(&self, cond_expr: Box<Expr>) -> Box<Expr> {
|
||||
let unlikely_path = self.cx.std_path(&[sym::intrinsics, sym::unlikely]);
|
||||
self.cx.expr_call(
|
||||
self.span,
|
||||
|
|
@ -145,7 +144,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
/// __capture0,
|
||||
/// ...
|
||||
/// );
|
||||
fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
|
||||
fn build_panic(&self, expr_str: &str, panic_path: Path) -> Box<Expr> {
|
||||
let escaped_expr_str = escape_to_fmt(expr_str);
|
||||
let initial = [
|
||||
TokenTree::token_joint(
|
||||
|
|
@ -176,9 +175,9 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
});
|
||||
self.cx.expr(
|
||||
self.span,
|
||||
ExprKind::MacCall(P(MacCall {
|
||||
ExprKind::MacCall(Box::new(MacCall {
|
||||
path: panic_path,
|
||||
args: P(DelimArgs {
|
||||
args: Box::new(DelimArgs {
|
||||
dspan: DelimSpan::from_single(self.span),
|
||||
delim: Delimiter::Parenthesis,
|
||||
tokens: initial.into_iter().chain(captures).collect::<TokenStream>(),
|
||||
|
|
@ -190,7 +189,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
/// Recursive function called until `cond_expr` and `fmt_str` are fully modified.
|
||||
///
|
||||
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
|
||||
fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
|
||||
fn manage_cond_expr(&mut self, expr: &mut Box<Expr>) {
|
||||
match &mut expr.kind {
|
||||
ExprKind::AddrOf(_, mutability, local_expr) => {
|
||||
self.with_is_consumed_management(matches!(mutability, Mutability::Mut), |this| {
|
||||
|
|
@ -331,7 +330,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
///
|
||||
/// `fmt_str`, the formatting string used for debugging, is constructed to show possible
|
||||
/// captured variables.
|
||||
fn manage_initial_capture(&mut self, expr: &mut P<Expr>, path_ident: Ident) {
|
||||
fn manage_initial_capture(&mut self, expr: &mut Box<Expr>, path_ident: Ident) {
|
||||
if self.paths.contains(&path_ident) {
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -360,7 +359,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
/// (&Wrapper(__local_bindN)).try_capture(&mut __captureN);
|
||||
/// __local_bindN
|
||||
/// }
|
||||
fn manage_try_capture(&mut self, capture: Ident, curr_capture_idx: usize, expr: &mut P<Expr>) {
|
||||
fn manage_try_capture(
|
||||
&mut self,
|
||||
capture: Ident,
|
||||
curr_capture_idx: usize,
|
||||
expr: &mut Box<Expr>,
|
||||
) {
|
||||
let local_bind_string = format!("__local_bind{curr_capture_idx}");
|
||||
let local_bind = Ident::new(Symbol::intern(&local_bind_string), self.span);
|
||||
self.local_bind_decls.push(self.cx.stmt_let(
|
||||
|
|
@ -441,20 +445,20 @@ fn escape_to_fmt(s: &str) -> String {
|
|||
rslt
|
||||
}
|
||||
|
||||
fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
|
||||
fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: Box<Expr>) -> Box<Expr> {
|
||||
cx.expr(sp, ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e))
|
||||
}
|
||||
|
||||
fn expr_method_call(
|
||||
cx: &ExtCtxt<'_>,
|
||||
seg: PathSegment,
|
||||
receiver: P<Expr>,
|
||||
args: ThinVec<P<Expr>>,
|
||||
receiver: Box<Expr>,
|
||||
args: ThinVec<Box<Expr>>,
|
||||
span: Span,
|
||||
) -> P<Expr> {
|
||||
) -> Box<Expr> {
|
||||
cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span })))
|
||||
}
|
||||
|
||||
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
|
||||
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: Box<Expr>) -> Box<Expr> {
|
||||
cx.expr(sp, ExprKind::Paren(e))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ mod llvm_enzyme {
|
|||
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
|
||||
valid_ty_for_activity,
|
||||
};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{Lit, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::*;
|
||||
use rustc_ast::visit::AssocCtxt::*;
|
||||
|
|
@ -27,7 +26,7 @@ mod llvm_enzyme {
|
|||
use crate::errors;
|
||||
|
||||
pub(crate) fn outer_normal_attr(
|
||||
kind: &P<rustc_ast::NormalAttr>,
|
||||
kind: &Box<rustc_ast::NormalAttr>,
|
||||
id: rustc_ast::AttrId,
|
||||
span: Span,
|
||||
) -> rustc_ast::Attribute {
|
||||
|
|
@ -73,7 +72,7 @@ mod llvm_enzyme {
|
|||
}
|
||||
|
||||
// Get information about the function the macro is applied to
|
||||
fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> {
|
||||
fn extract_item_info(iitem: &Box<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> {
|
||||
match &iitem.kind {
|
||||
ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
|
||||
Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
|
||||
|
|
@ -346,7 +345,7 @@ mod llvm_enzyme {
|
|||
define_opaque: None,
|
||||
});
|
||||
let mut rustc_ad_attr =
|
||||
P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));
|
||||
Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));
|
||||
|
||||
let ts2: Vec<TokenTree> = vec![TokenTree::Token(
|
||||
Token::new(TokenKind::Ident(sym::never, false.into()), span),
|
||||
|
|
@ -363,7 +362,7 @@ mod llvm_enzyme {
|
|||
args: ast::AttrArgs::Delimited(never_arg),
|
||||
tokens: None,
|
||||
};
|
||||
let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None });
|
||||
let inline_never_attr = Box::new(ast::NormalAttr { item: inline_item, tokens: None });
|
||||
let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
|
||||
let attr = outer_normal_attr(&rustc_ad_attr, new_id, span);
|
||||
let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
|
||||
|
|
@ -433,7 +432,7 @@ mod llvm_enzyme {
|
|||
let d_annotatable = match &item {
|
||||
Annotatable::AssocItem(_, _) => {
|
||||
let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf);
|
||||
let d_fn = P(ast::AssocItem {
|
||||
let d_fn = Box::new(ast::AssocItem {
|
||||
attrs: thin_vec![d_attr, inline_never],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span,
|
||||
|
|
@ -453,7 +452,7 @@ mod llvm_enzyme {
|
|||
let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
|
||||
d_fn.vis = vis;
|
||||
|
||||
Annotatable::Stmt(P(ast::Stmt {
|
||||
Annotatable::Stmt(Box::new(ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::StmtKind::Item(d_fn),
|
||||
span,
|
||||
|
|
@ -506,7 +505,7 @@ mod llvm_enzyme {
|
|||
idents: &[Ident],
|
||||
errored: bool,
|
||||
generics: &Generics,
|
||||
) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) {
|
||||
) -> (Box<ast::Block>, Box<ast::Expr>, Box<ast::Expr>, Box<ast::Expr>) {
|
||||
let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]);
|
||||
let noop = ast::InlineAsm {
|
||||
asm_macro: ast::AsmMacro::Asm,
|
||||
|
|
@ -517,7 +516,7 @@ mod llvm_enzyme {
|
|||
options: ast::InlineAsmOptions::PURE | ast::InlineAsmOptions::NOMEM,
|
||||
line_spans: vec![],
|
||||
};
|
||||
let noop_expr = ecx.expr_asm(span, P(noop));
|
||||
let noop_expr = ecx.expr_asm(span, Box::new(noop));
|
||||
let unsf = ast::BlockCheckMode::Unsafe(ast::UnsafeSource::CompilerGenerated);
|
||||
let unsf_block = ast::Block {
|
||||
stmts: thin_vec![ecx.stmt_semi(noop_expr)],
|
||||
|
|
@ -526,7 +525,7 @@ mod llvm_enzyme {
|
|||
rules: unsf,
|
||||
span,
|
||||
};
|
||||
let unsf_expr = ecx.expr_block(P(unsf_block));
|
||||
let unsf_expr = ecx.expr_block(Box::new(unsf_block));
|
||||
let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path));
|
||||
let primal_call = gen_primal_call(ecx, span, primal, idents, generics);
|
||||
let black_box_primal_call = ecx.expr_call(
|
||||
|
|
@ -578,7 +577,7 @@ mod llvm_enzyme {
|
|||
idents: Vec<Ident>,
|
||||
errored: bool,
|
||||
generics: &Generics,
|
||||
) -> P<ast::Block> {
|
||||
) -> Box<ast::Block> {
|
||||
let new_decl_span = d_sig.span;
|
||||
|
||||
// Just adding some default inline-asm and black_box usages to prevent early inlining
|
||||
|
|
@ -634,7 +633,7 @@ mod llvm_enzyme {
|
|||
return body;
|
||||
}
|
||||
|
||||
let mut exprs: P<ast::Expr> = primal_call;
|
||||
let mut exprs: Box<ast::Expr> = primal_call;
|
||||
let d_ret_ty = match d_sig.decl.output {
|
||||
FnRetTy::Ty(ref ty) => ty.clone(),
|
||||
FnRetTy::Default(span) => {
|
||||
|
|
@ -653,7 +652,7 @@ mod llvm_enzyme {
|
|||
} else {
|
||||
let q = QSelf { ty: d_ret_ty, path_span: span, position: 0 };
|
||||
let y = ExprKind::Path(
|
||||
Some(P(q)),
|
||||
Some(Box::new(q)),
|
||||
ecx.path_ident(span, Ident::with_dummy_span(kw::Default)),
|
||||
);
|
||||
let default_call_expr = ecx.expr(span, y);
|
||||
|
|
@ -703,7 +702,7 @@ mod llvm_enzyme {
|
|||
primal: Ident,
|
||||
idents: &[Ident],
|
||||
generics: &Generics,
|
||||
) -> P<ast::Expr> {
|
||||
) -> Box<ast::Expr> {
|
||||
let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower;
|
||||
|
||||
if has_self {
|
||||
|
|
@ -740,7 +739,7 @@ mod llvm_enzyme {
|
|||
},
|
||||
);
|
||||
|
||||
ast::AngleBracketedArg::Arg(ast::GenericArg::Type(P(ast::Ty {
|
||||
ast::AngleBracketedArg::Arg(ast::GenericArg::Type(Box::new(ast::Ty {
|
||||
id: type_param.id,
|
||||
span,
|
||||
kind: generic_param,
|
||||
|
|
@ -750,7 +749,7 @@ mod llvm_enzyme {
|
|||
.collect();
|
||||
|
||||
function_path.args =
|
||||
Some(P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
|
||||
Some(Box::new(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
|
||||
span,
|
||||
args: generated_generic_types,
|
||||
})));
|
||||
|
|
@ -856,7 +855,7 @@ mod llvm_enzyme {
|
|||
for i in 0..x.width {
|
||||
let mut shadow_arg = arg.clone();
|
||||
// We += into the shadow in reverse mode.
|
||||
shadow_arg.ty = P(assure_mut_ref(&arg.ty));
|
||||
shadow_arg.ty = Box::new(assure_mut_ref(&arg.ty));
|
||||
let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind {
|
||||
ident.name
|
||||
} else {
|
||||
|
|
@ -866,7 +865,7 @@ mod llvm_enzyme {
|
|||
let name: String = format!("d{}_{}", old_name, i);
|
||||
new_inputs.push(name.clone());
|
||||
let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span);
|
||||
shadow_arg.pat = P(ast::Pat {
|
||||
shadow_arg.pat = Box::new(ast::Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingMode::NONE, ident, None),
|
||||
span: shadow_arg.pat.span,
|
||||
|
|
@ -898,7 +897,7 @@ mod llvm_enzyme {
|
|||
let name: String = format!("b{}_{}", old_name, i);
|
||||
new_inputs.push(name.clone());
|
||||
let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span);
|
||||
shadow_arg.pat = P(ast::Pat {
|
||||
shadow_arg.pat = Box::new(ast::Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingMode::NONE, ident, None),
|
||||
span: shadow_arg.pat.span,
|
||||
|
|
@ -942,7 +941,7 @@ mod llvm_enzyme {
|
|||
let shadow_arg = ast::Param {
|
||||
attrs: ThinVec::new(),
|
||||
ty: ty.clone(),
|
||||
pat: P(ast::Pat {
|
||||
pat: Box::new(ast::Pat {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: PatKind::Ident(BindingMode::NONE, ident, None),
|
||||
span: ty.span,
|
||||
|
|
@ -966,7 +965,12 @@ mod llvm_enzyme {
|
|||
FnRetTy::Default(span) => {
|
||||
// We want to return std::hint::black_box(()).
|
||||
let kind = TyKind::Tup(ThinVec::new());
|
||||
let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None });
|
||||
let ty = Box::new(rustc_ast::Ty {
|
||||
kind,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span,
|
||||
tokens: None,
|
||||
});
|
||||
d_decl.output = FnRetTy::Ty(ty.clone());
|
||||
assert!(matches!(x.ret_activity, DiffActivity::None));
|
||||
// this won't be used below, so any type would be fine.
|
||||
|
|
@ -987,7 +991,7 @@ mod llvm_enzyme {
|
|||
};
|
||||
TyKind::Array(ty.clone(), anon_const)
|
||||
};
|
||||
let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
|
||||
let ty = Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
|
||||
d_decl.output = FnRetTy::Ty(ty);
|
||||
}
|
||||
if matches!(x.ret_activity, DiffActivity::DualOnly | DiffActivity::DualvOnly) {
|
||||
|
|
@ -1000,7 +1004,8 @@ mod llvm_enzyme {
|
|||
value: ecx.expr_usize(span, x.width as usize),
|
||||
};
|
||||
let kind = TyKind::Array(ty.clone(), anon_const);
|
||||
let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
|
||||
let ty =
|
||||
Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
|
||||
d_decl.output = FnRetTy::Ty(ty);
|
||||
}
|
||||
}
|
||||
|
|
@ -1022,14 +1027,14 @@ mod llvm_enzyme {
|
|||
act_ret.insert(0, ty.clone());
|
||||
}
|
||||
let kind = TyKind::Tup(act_ret);
|
||||
P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None })
|
||||
Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None })
|
||||
}
|
||||
FnRetTy::Default(span) => {
|
||||
if act_ret.len() == 1 {
|
||||
act_ret[0].clone()
|
||||
} else {
|
||||
let kind = TyKind::Tup(act_ret.iter().map(|arg| arg.clone()).collect());
|
||||
P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None })
|
||||
Box::new(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None })
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ impl MultiItemModifier for Expander {
|
|||
item: Annotatable,
|
||||
_is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
||||
let template = AttributeTemplate { list: Some(&["path"]), ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&ecx.sess.psess,
|
||||
meta_item,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use core::ops::ControlFlow;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::mut_visit::MutVisitor;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::{Attribute, HasAttrs, HasTokens, NodeId, mut_visit, visit};
|
||||
use rustc_errors::PResult;
|
||||
|
|
@ -132,7 +131,7 @@ impl CfgEval<'_> {
|
|||
let stmt = parser
|
||||
.parse_stmt_without_recovery(false, ForceCollect::Yes, false)?
|
||||
.unwrap();
|
||||
Annotatable::Stmt(P(self.flat_map_stmt(stmt).pop().unwrap()))
|
||||
Annotatable::Stmt(Box::new(self.flat_map_stmt(stmt).pop().unwrap()))
|
||||
}
|
||||
Annotatable::Expr(_) => {
|
||||
let mut expr = parser.parse_expr_force_collect()?;
|
||||
|
|
@ -166,7 +165,7 @@ impl MutVisitor for CfgEval<'_> {
|
|||
mut_visit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
fn filter_map_expr(&mut self, expr: Box<ast::Expr>) -> Option<Box<ast::Expr>> {
|
||||
let mut expr = configure!(self, expr);
|
||||
mut_visit::walk_expr(self, &mut expr);
|
||||
Some(expr)
|
||||
|
|
@ -185,24 +184,24 @@ impl MutVisitor for CfgEval<'_> {
|
|||
mut_visit::walk_flat_map_stmt(self, stmt)
|
||||
}
|
||||
|
||||
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
fn flat_map_item(&mut self, item: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
|
||||
let item = configure!(self, item);
|
||||
mut_visit::walk_flat_map_item(self, item)
|
||||
}
|
||||
|
||||
fn flat_map_assoc_item(
|
||||
&mut self,
|
||||
item: P<ast::AssocItem>,
|
||||
item: Box<ast::AssocItem>,
|
||||
ctxt: AssocCtxt,
|
||||
) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
) -> SmallVec<[Box<ast::AssocItem>; 1]> {
|
||||
let item = configure!(self, item);
|
||||
mut_visit::walk_flat_map_assoc_item(self, item, ctxt)
|
||||
}
|
||||
|
||||
fn flat_map_foreign_item(
|
||||
&mut self,
|
||||
foreign_item: P<ast::ForeignItem>,
|
||||
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
||||
foreign_item: Box<ast::ForeignItem>,
|
||||
) -> SmallVec<[Box<ast::ForeignItem>; 1]> {
|
||||
let foreign_item = configure!(self, foreign_item);
|
||||
mut_visit::walk_flat_map_foreign_item(self, foreign_item)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{ExprKind, LitIntType, LitKind, StrStyle, UintTy, token};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
|
|
@ -90,7 +89,7 @@ fn handle_array_element(
|
|||
cx: &ExtCtxt<'_>,
|
||||
guar: &mut Option<ErrorGuaranteed>,
|
||||
missing_literals: &mut Vec<rustc_span::Span>,
|
||||
expr: &P<rustc_ast::Expr>,
|
||||
expr: &Box<rustc_ast::Expr>,
|
||||
) -> Option<u8> {
|
||||
let dcx = cx.dcx();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ impl MultiItemModifier for Expander {
|
|||
let (sess, features) = (ecx.sess, ecx.ecfg.features);
|
||||
let result =
|
||||
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
||||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
let template = AttributeTemplate {
|
||||
list: Some(&["Trait1, Trait2, ..."]),
|
||||
..Default::default()
|
||||
};
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&sess.psess,
|
||||
meta_item,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::{Span, sym};
|
||||
|
|
@ -119,7 +118,7 @@ fn get_substructure_equality_expr(
|
|||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
substructure: &Substructure<'_>,
|
||||
) -> P<Expr> {
|
||||
) -> Box<Expr> {
|
||||
use SubstructureFields::*;
|
||||
|
||||
match substructure.fields {
|
||||
|
|
@ -180,7 +179,7 @@ fn get_substructure_equality_expr(
|
|||
///
|
||||
/// Panics if there are not exactly two arguments to compare (should be `self`
|
||||
/// and `other`).
|
||||
fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> P<Expr> {
|
||||
fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> Box<Expr> {
|
||||
let [rhs] = &field.other_selflike_exprs[..] else {
|
||||
cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
|
||||
};
|
||||
|
|
@ -198,7 +197,7 @@ fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> P<Expr> {
|
|||
/// This is used to strip away any number of leading `&` from an expression
|
||||
/// (e.g., `&&&T` becomes `T`). Only removes immutable references; mutable
|
||||
/// references are preserved.
|
||||
fn peel_refs(mut expr: &P<Expr>) -> P<Expr> {
|
||||
fn peel_refs(mut expr: &Box<Expr>) -> Box<Expr> {
|
||||
while let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = &expr.kind {
|
||||
expr = &inner;
|
||||
}
|
||||
|
|
@ -210,7 +209,7 @@ fn peel_refs(mut expr: &P<Expr>) -> P<Expr> {
|
|||
///
|
||||
/// If the given expression is a block, it is wrapped in parentheses; otherwise,
|
||||
/// it is returned unchanged.
|
||||
fn wrap_block_expr(cx: &ExtCtxt<'_>, expr: P<Expr>) -> P<Expr> {
|
||||
fn wrap_block_expr(cx: &ExtCtxt<'_>, expr: Box<Expr>) -> Box<Expr> {
|
||||
if matches!(&expr.kind, ExprKind::Block(..)) {
|
||||
return cx.expr_paren(expr.span, expr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,11 +108,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
|||
cx.item(
|
||||
span,
|
||||
attrs.clone(),
|
||||
ast::ItemKind::Impl(Box::new(ast::Impl {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
ast::ItemKind::Impl(ast::Impl {
|
||||
generics: Generics {
|
||||
params: generics
|
||||
.params
|
||||
|
|
@ -137,10 +133,16 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
|||
where_clause: generics.where_clause.clone(),
|
||||
span: generics.span,
|
||||
},
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
trait_ref,
|
||||
})),
|
||||
self_ty: self_type.clone(),
|
||||
items: ThinVec::new(),
|
||||
})),
|
||||
}),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
|
@ -152,16 +154,18 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
|||
let item = cx.item(
|
||||
span,
|
||||
attrs.clone(),
|
||||
ast::ItemKind::Impl(Box::new(ast::Impl {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
ast::ItemKind::Impl(ast::Impl {
|
||||
generics,
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
trait_ref,
|
||||
})),
|
||||
self_ty: self_type.clone(),
|
||||
items: ThinVec::new(),
|
||||
})),
|
||||
}),
|
||||
);
|
||||
push(Annotatable::Item(item));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
|
|||
field: &FieldInfo,
|
||||
index: usize,
|
||||
len: usize,
|
||||
) -> ast::ptr::P<ast::Expr> {
|
||||
) -> Box<ast::Expr> {
|
||||
if index < len - 1 {
|
||||
field.self_expr.clone()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ pub(crate) fn expand_deriving_default(
|
|||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn default_call(cx: &ExtCtxt<'_>, span: Span) -> ast::ptr::P<ast::Expr> {
|
||||
fn default_call(cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Expr> {
|
||||
// Note that `kw::Default` is "default" and `sym::Default` is "Default"!
|
||||
let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
|
||||
cx.expr_call_global(span, default_ident, ThinVec::new())
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ use std::{iter, vec};
|
|||
|
||||
pub(crate) use StaticFields::*;
|
||||
pub(crate) use SubstructureFields::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use rustc_ast::{
|
||||
|
|
@ -272,7 +271,7 @@ pub(crate) struct Substructure<'a> {
|
|||
pub type_ident: Ident,
|
||||
/// Verbatim access to any non-selflike arguments, i.e. arguments that
|
||||
/// don't have type `&Self`.
|
||||
pub nonselflike_args: &'a [P<Expr>],
|
||||
pub nonselflike_args: &'a [Box<Expr>],
|
||||
pub fields: &'a SubstructureFields<'a>,
|
||||
}
|
||||
|
||||
|
|
@ -284,10 +283,10 @@ pub(crate) struct FieldInfo {
|
|||
pub name: Option<Ident>,
|
||||
/// The expression corresponding to this field of `self`
|
||||
/// (specifically, a reference to it).
|
||||
pub self_expr: P<Expr>,
|
||||
pub self_expr: Box<Expr>,
|
||||
/// The expressions corresponding to references to this field in
|
||||
/// the other selflike arguments.
|
||||
pub other_selflike_exprs: Vec<P<Expr>>,
|
||||
pub other_selflike_exprs: Vec<Box<Expr>>,
|
||||
pub maybe_scalar: bool,
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +322,7 @@ pub(crate) enum SubstructureFields<'a> {
|
|||
/// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as
|
||||
/// if they were fields. The second field is the expression to combine the
|
||||
/// discriminant expression with; it will be `None` if no match is necessary.
|
||||
EnumDiscr(FieldInfo, Option<P<Expr>>),
|
||||
EnumDiscr(FieldInfo, Option<Box<Expr>>),
|
||||
|
||||
/// A static method where `Self` is a struct.
|
||||
StaticStruct(&'a ast::VariantData, StaticFields),
|
||||
|
|
@ -345,7 +344,7 @@ pub(crate) fn combine_substructure(
|
|||
|
||||
struct TypeParameter {
|
||||
bound_generic_params: ThinVec<ast::GenericParam>,
|
||||
ty: P<ast::Ty>,
|
||||
ty: Box<ast::Ty>,
|
||||
}
|
||||
|
||||
/// The code snippets built up for derived code are sometimes used as blocks
|
||||
|
|
@ -354,23 +353,23 @@ struct TypeParameter {
|
|||
/// avoiding the insertion of any unnecessary blocks.
|
||||
///
|
||||
/// The statements come before the expression.
|
||||
pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<P<Expr>>);
|
||||
pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<Box<Expr>>);
|
||||
|
||||
impl BlockOrExpr {
|
||||
pub(crate) fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr {
|
||||
BlockOrExpr(stmts, None)
|
||||
}
|
||||
|
||||
pub(crate) fn new_expr(expr: P<Expr>) -> BlockOrExpr {
|
||||
pub(crate) fn new_expr(expr: Box<Expr>) -> BlockOrExpr {
|
||||
BlockOrExpr(ThinVec::new(), Some(expr))
|
||||
}
|
||||
|
||||
pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr {
|
||||
pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<Box<Expr>>) -> BlockOrExpr {
|
||||
BlockOrExpr(stmts, expr)
|
||||
}
|
||||
|
||||
// Converts it into a block.
|
||||
fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> P<ast::Block> {
|
||||
fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Block> {
|
||||
if let Some(expr) = self.1 {
|
||||
self.0.push(cx.stmt_expr(expr));
|
||||
}
|
||||
|
|
@ -378,7 +377,7 @@ impl BlockOrExpr {
|
|||
}
|
||||
|
||||
// Converts it into an expression.
|
||||
fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> {
|
||||
fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> Box<Expr> {
|
||||
if self.0.is_empty() {
|
||||
match self.1 {
|
||||
None => cx.expr_block(cx.block(span, ThinVec::new())),
|
||||
|
|
@ -432,7 +431,7 @@ fn find_type_parameters(
|
|||
{
|
||||
self.type_params.push(TypeParameter {
|
||||
bound_generic_params: self.bound_generic_params_stack.clone(),
|
||||
ty: P(ty.clone()),
|
||||
ty: Box::new(ty.clone()),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +543,7 @@ impl<'a> TraitDef<'a> {
|
|||
})
|
||||
.cloned(),
|
||||
);
|
||||
push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
|
||||
push(Annotatable::Item(Box::new(ast::Item { attrs, ..(*newitem).clone() })))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
@ -590,15 +589,15 @@ impl<'a> TraitDef<'a> {
|
|||
cx: &ExtCtxt<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
field_tys: Vec<P<ast::Ty>>,
|
||||
methods: Vec<P<ast::AssocItem>>,
|
||||
field_tys: Vec<Box<ast::Ty>>,
|
||||
methods: Vec<Box<ast::AssocItem>>,
|
||||
is_packed: bool,
|
||||
) -> P<ast::Item> {
|
||||
) -> Box<ast::Item> {
|
||||
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
|
||||
|
||||
// Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
|
||||
let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
|
||||
P(ast::AssocItem {
|
||||
Box::new(ast::AssocItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
vis: ast::Visibility {
|
||||
|
|
@ -827,21 +826,25 @@ impl<'a> TraitDef<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
|
||||
cx.item(
|
||||
self.span,
|
||||
attrs,
|
||||
ast::ItemKind::Impl(Box::new(ast::Impl {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
|
||||
ast::ItemKind::Impl(ast::Impl {
|
||||
generics: trait_generics,
|
||||
of_trait: opt_trait_ref,
|
||||
of_trait: Some(Box::new(ast::TraitImplHeader {
|
||||
safety: ast::Safety::Default,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: if self.is_const {
|
||||
ast::Const::Yes(DUMMY_SP)
|
||||
} else {
|
||||
ast::Const::No
|
||||
},
|
||||
trait_ref,
|
||||
})),
|
||||
self_ty: self_type,
|
||||
items: methods.into_iter().chain(associated_types).collect(),
|
||||
})),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -853,8 +856,8 @@ impl<'a> TraitDef<'a> {
|
|||
generics: &Generics,
|
||||
from_scratch: bool,
|
||||
is_packed: bool,
|
||||
) -> P<ast::Item> {
|
||||
let field_tys: Vec<P<ast::Ty>> =
|
||||
) -> Box<ast::Item> {
|
||||
let field_tys: Vec<Box<ast::Ty>> =
|
||||
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
|
||||
|
||||
let methods = self
|
||||
|
|
@ -906,7 +909,7 @@ impl<'a> TraitDef<'a> {
|
|||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
from_scratch: bool,
|
||||
) -> P<ast::Item> {
|
||||
) -> Box<ast::Item> {
|
||||
let mut field_tys = Vec::new();
|
||||
|
||||
for variant in &enum_def.variants {
|
||||
|
|
@ -962,7 +965,7 @@ impl<'a> MethodDef<'a> {
|
|||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
fields: &SubstructureFields<'_>,
|
||||
) -> BlockOrExpr {
|
||||
let span = trait_.span;
|
||||
|
|
@ -978,7 +981,7 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'_>,
|
||||
generics: &Generics,
|
||||
type_ident: Ident,
|
||||
) -> P<ast::Ty> {
|
||||
) -> Box<ast::Ty> {
|
||||
self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
|
||||
}
|
||||
|
||||
|
|
@ -999,7 +1002,8 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
) -> (Option<ast::ExplicitSelf>, ThinVec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
|
||||
) -> (Option<ast::ExplicitSelf>, ThinVec<Box<Expr>>, Vec<Box<Expr>>, Vec<(Ident, Box<ast::Ty>)>)
|
||||
{
|
||||
let mut selflike_args = ThinVec::new();
|
||||
let mut nonselflike_args = Vec::new();
|
||||
let mut nonself_arg_tys = Vec::new();
|
||||
|
|
@ -1036,9 +1040,9 @@ impl<'a> MethodDef<'a> {
|
|||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
explicit_self: Option<ast::ExplicitSelf>,
|
||||
nonself_arg_tys: Vec<(Ident, P<ast::Ty>)>,
|
||||
nonself_arg_tys: Vec<(Ident, Box<ast::Ty>)>,
|
||||
body: BlockOrExpr,
|
||||
) -> P<ast::AssocItem> {
|
||||
) -> Box<ast::AssocItem> {
|
||||
let span = trait_.span;
|
||||
// Create the generics that aren't for `Self`.
|
||||
let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
|
||||
|
|
@ -1065,7 +1069,7 @@ impl<'a> MethodDef<'a> {
|
|||
let defaultness = ast::Defaultness::Final;
|
||||
|
||||
// Create the method.
|
||||
P(ast::AssocItem {
|
||||
Box::new(ast::AssocItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: self.attributes.clone(),
|
||||
span,
|
||||
|
|
@ -1128,8 +1132,8 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'b>,
|
||||
struct_def: &'b VariantData,
|
||||
type_ident: Ident,
|
||||
selflike_args: &[P<Expr>],
|
||||
nonselflike_args: &[P<Expr>],
|
||||
selflike_args: &[Box<Expr>],
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
is_packed: bool,
|
||||
) -> BlockOrExpr {
|
||||
assert!(selflike_args.len() == 1 || selflike_args.len() == 2);
|
||||
|
|
@ -1151,7 +1155,7 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'_>,
|
||||
struct_def: &VariantData,
|
||||
type_ident: Ident,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
) -> BlockOrExpr {
|
||||
let summary = trait_.summarise_struct(cx, struct_def);
|
||||
|
||||
|
|
@ -1205,8 +1209,8 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'b>,
|
||||
enum_def: &'b EnumDef,
|
||||
type_ident: Ident,
|
||||
mut selflike_args: ThinVec<P<Expr>>,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
mut selflike_args: ThinVec<Box<Expr>>,
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
) -> BlockOrExpr {
|
||||
assert!(
|
||||
!selflike_args.is_empty(),
|
||||
|
|
@ -1418,7 +1422,7 @@ impl<'a> MethodDef<'a> {
|
|||
// ...
|
||||
// _ => ::core::intrinsics::unreachable(),
|
||||
// }
|
||||
let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
|
||||
let get_match_expr = |mut selflike_args: ThinVec<Box<Expr>>| {
|
||||
let match_arg = if selflike_args.len() == 1 {
|
||||
selflike_args.pop().unwrap()
|
||||
} else {
|
||||
|
|
@ -1454,7 +1458,7 @@ impl<'a> MethodDef<'a> {
|
|||
trait_: &TraitDef<'_>,
|
||||
enum_def: &EnumDef,
|
||||
type_ident: Ident,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
nonselflike_args: &[Box<Expr>],
|
||||
) -> BlockOrExpr {
|
||||
self.call_substructure_method(
|
||||
cx,
|
||||
|
|
@ -1503,7 +1507,7 @@ impl<'a> TraitDef<'a> {
|
|||
struct_def: &'a VariantData,
|
||||
prefixes: &[String],
|
||||
by_ref: ByRef,
|
||||
) -> ThinVec<P<ast::Pat>> {
|
||||
) -> ThinVec<Box<ast::Pat>> {
|
||||
prefixes
|
||||
.iter()
|
||||
.map(|prefix| {
|
||||
|
|
@ -1558,7 +1562,7 @@ impl<'a> TraitDef<'a> {
|
|||
|
||||
fn create_fields<F>(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec<FieldInfo>
|
||||
where
|
||||
F: Fn(usize, &ast::FieldDef, Span) -> Vec<P<ast::Expr>>,
|
||||
F: Fn(usize, &ast::FieldDef, Span) -> Vec<Box<ast::Expr>>,
|
||||
{
|
||||
struct_def
|
||||
.fields()
|
||||
|
|
@ -1606,7 +1610,7 @@ impl<'a> TraitDef<'a> {
|
|||
fn create_struct_field_access_fields(
|
||||
&self,
|
||||
cx: &ExtCtxt<'_>,
|
||||
selflike_args: &[P<Expr>],
|
||||
selflike_args: &[Box<Expr>],
|
||||
struct_def: &'a VariantData,
|
||||
is_packed: bool,
|
||||
) -> Vec<FieldInfo> {
|
||||
|
|
@ -1651,7 +1655,7 @@ pub(crate) enum CsFold<'a> {
|
|||
|
||||
/// The combination of two field expressions. E.g. for `PartialEq::eq` this
|
||||
/// is something like `<field1 equality> && <field2 equality>`.
|
||||
Combine(Span, P<Expr>, P<Expr>),
|
||||
Combine(Span, Box<Expr>, Box<Expr>),
|
||||
|
||||
// The fallback case for a struct or enum variant with no fields.
|
||||
Fieldless,
|
||||
|
|
@ -1665,9 +1669,9 @@ pub(crate) fn cs_fold<F>(
|
|||
trait_span: Span,
|
||||
substructure: &Substructure<'_>,
|
||||
mut f: F,
|
||||
) -> P<Expr>
|
||||
) -> Box<Expr>
|
||||
where
|
||||
F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> P<Expr>,
|
||||
F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> Box<Expr>,
|
||||
{
|
||||
match substructure.fields {
|
||||
EnumMatching(.., all_fields) | Struct(_, all_fields) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
//! when specifying impls to be derived.
|
||||
|
||||
pub(crate) use Ty::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_span::source_map::respan;
|
||||
|
|
@ -41,7 +40,7 @@ impl Path {
|
|||
span: Span,
|
||||
self_ty: Ident,
|
||||
self_generics: &Generics,
|
||||
) -> P<ast::Ty> {
|
||||
) -> Box<ast::Ty> {
|
||||
cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
|
||||
}
|
||||
pub(crate) fn to_path(
|
||||
|
|
@ -90,7 +89,7 @@ impl Ty {
|
|||
span: Span,
|
||||
self_ty: Ident,
|
||||
self_generics: &Generics,
|
||||
) -> P<ast::Ty> {
|
||||
) -> Box<ast::Ty> {
|
||||
match self {
|
||||
Ref(ty, mutbl) => {
|
||||
let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
|
||||
|
|
@ -192,7 +191,7 @@ impl Bounds {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P<Expr>, ast::ExplicitSelf) {
|
||||
pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (Box<Expr>, ast::ExplicitSelf) {
|
||||
// This constructs a fresh `self` path.
|
||||
let self_path = cx.expr_self(span);
|
||||
let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! The compiler code necessary to implement the `#[derive]` extensions.
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{GenericArg, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
|
@ -66,7 +65,7 @@ impl MultiItemModifier for BuiltinDerive {
|
|||
&mut |a| {
|
||||
// Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
|
||||
// to the function
|
||||
items.push(Annotatable::Stmt(P(ast::Stmt {
|
||||
items.push(Annotatable::Stmt(Box::new(ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::StmtKind::Item(a.expect_item()),
|
||||
span,
|
||||
|
|
@ -91,20 +90,20 @@ fn call_intrinsic(
|
|||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
intrinsic: Symbol,
|
||||
args: ThinVec<P<ast::Expr>>,
|
||||
) -> P<ast::Expr> {
|
||||
args: ThinVec<Box<ast::Expr>>,
|
||||
) -> Box<ast::Expr> {
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let path = cx.std_path(&[sym::intrinsics, intrinsic]);
|
||||
cx.expr_call_global(span, path, args)
|
||||
}
|
||||
|
||||
/// Constructs an expression that calls the `unreachable` intrinsic.
|
||||
fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
|
||||
fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Expr> {
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let path = cx.std_path(&[sym::intrinsics, sym::unreachable]);
|
||||
let call = cx.expr_call_global(span, path, ThinVec::new());
|
||||
|
||||
cx.expr_block(P(ast::Block {
|
||||
cx.expr_block(Box::new(ast::Block {
|
||||
stmts: thin_vec![cx.stmt_expr(call)],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
|
||||
|
|
@ -116,7 +115,7 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
|
|||
fn assert_ty_bounds(
|
||||
cx: &ExtCtxt<'_>,
|
||||
stmts: &mut ThinVec<ast::Stmt>,
|
||||
ty: P<ast::Ty>,
|
||||
ty: Box<ast::Ty>,
|
||||
span: Span,
|
||||
assert_path: &[Symbol],
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::*;
|
||||
|
|
@ -48,7 +47,7 @@ fn expand<'cx>(
|
|||
ExpandResult::Ready(MacEager::expr(
|
||||
cx.expr(
|
||||
sp,
|
||||
ExprKind::MacCall(P(MacCall {
|
||||
ExprKind::MacCall(Box::new(MacCall {
|
||||
path: Path {
|
||||
span: sp,
|
||||
segments: cx
|
||||
|
|
@ -58,7 +57,7 @@ fn expand<'cx>(
|
|||
.collect(),
|
||||
tokens: None,
|
||||
},
|
||||
args: P(DelimArgs {
|
||||
args: Box::new(DelimArgs {
|
||||
dspan: DelimSpan::from_single(sp),
|
||||
delim: Delimiter::Parenthesis,
|
||||
tokens: tts,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use parse::Position::ArgumentNamed;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{
|
||||
Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
|
||||
|
|
@ -45,7 +44,7 @@ use PositionUsedAs::*;
|
|||
|
||||
#[derive(Debug)]
|
||||
struct MacroInput {
|
||||
fmtstr: P<Expr>,
|
||||
fmtstr: Box<Expr>,
|
||||
args: FormatArguments,
|
||||
/// Whether the first argument was a string literal or a result from eager macro expansion.
|
||||
/// If it's not a string literal, we disallow implicit argument capturing.
|
||||
|
|
@ -1018,7 +1017,7 @@ fn expand_format_args_impl<'cx>(
|
|||
};
|
||||
match mac {
|
||||
Ok(format_args) => {
|
||||
MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
|
||||
MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(Box::new(format_args))))
|
||||
}
|
||||
Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,18 +346,18 @@ pub(crate) mod printf {
|
|||
// ```regex
|
||||
// (?x)
|
||||
// ^ %
|
||||
// (?: (?P<parameter> \d+) \$ )?
|
||||
// (?P<flags> [-+ 0\#']* )
|
||||
// (?P<width> \d+ | \* (?: (?P<widtha> \d+) \$ )? )?
|
||||
// (?: \. (?P<precision> \d+ | \* (?: (?P<precisiona> \d+) \$ )? ) )?
|
||||
// (?P<length>
|
||||
// (?: (?Box<parameter> \d+) \$ )?
|
||||
// (?Box<flags> [-+ 0\#']* )
|
||||
// (?Box<width> \d+ | \* (?: (?Box<widtha> \d+) \$ )? )?
|
||||
// (?: \. (?Box<precision> \d+ | \* (?: (?Box<precisiona> \d+) \$ )? ) )?
|
||||
// (?Box<length>
|
||||
// # Standard
|
||||
// hh | h | ll | l | L | z | j | t
|
||||
//
|
||||
// # Other
|
||||
// | I32 | I64 | I | q
|
||||
// )?
|
||||
// (?P<type> . )
|
||||
// (?Box<type> . )
|
||||
// ```
|
||||
|
||||
// Used to establish the full span at the end.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorMethod, AllocatorMethodInput, AllocatorTy, global_fn_name,
|
||||
};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{
|
||||
self as ast, AttrVec, Expr, Fn, FnHeader, FnSig, Generics, ItemKind, Mutability, Param, Safety,
|
||||
Stmt, StmtKind, Ty, TyKind,
|
||||
|
|
@ -51,7 +50,7 @@ pub(crate) fn expand(
|
|||
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
} else {
|
||||
Annotatable::Item(const_item)
|
||||
};
|
||||
|
|
@ -90,7 +89,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
self.cx.stmt_item(self.ty_span, item)
|
||||
}
|
||||
|
||||
fn call_allocator(&self, method: Symbol, mut args: ThinVec<P<Expr>>) -> P<Expr> {
|
||||
fn call_allocator(&self, method: Symbol, mut args: ThinVec<Box<Expr>>) -> Box<Expr> {
|
||||
let method = self.cx.std_path(&[sym::alloc, sym::GlobalAlloc, method]);
|
||||
let method = self.cx.expr_path(self.cx.path(self.ty_span, method));
|
||||
let allocator = self.cx.path_ident(self.ty_span, self.global);
|
||||
|
|
@ -105,7 +104,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)]
|
||||
}
|
||||
|
||||
fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec<Param>) -> P<Expr> {
|
||||
fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec<Param>) -> Box<Expr> {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
// If an allocator method is ever introduced having multiple
|
||||
|
|
@ -148,7 +147,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn ret_ty(&self, ty: &AllocatorTy) -> P<Ty> {
|
||||
fn ret_ty(&self, ty: &AllocatorTy) -> Box<Ty> {
|
||||
match *ty {
|
||||
AllocatorTy::ResultPtr => self.ptr_u8(),
|
||||
|
||||
|
|
@ -160,12 +159,12 @@ impl AllocFnFactory<'_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn usize(&self) -> P<Ty> {
|
||||
fn usize(&self) -> Box<Ty> {
|
||||
let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
|
||||
self.cx.ty_path(usize)
|
||||
}
|
||||
|
||||
fn ptr_u8(&self) -> P<Ty> {
|
||||
fn ptr_u8(&self) -> Box<Ty> {
|
||||
let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
|
||||
let ty_u8 = self.cx.ty_path(u8);
|
||||
self.cx.ty_ptr(self.span, ty_u8, Mutability::Mut)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token};
|
||||
use rustc_errors::PResult;
|
||||
|
|
@ -24,7 +23,7 @@ fn parse_closure<'a>(
|
|||
cx: &mut ExtCtxt<'a>,
|
||||
span: Span,
|
||||
stream: TokenStream,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
) -> PResult<'a, Box<Expr>> {
|
||||
let mut closure_parser = cx.new_parser_from_tts(stream);
|
||||
|
||||
let coroutine_kind = Some(CoroutineKind::Gen {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
|
||||
use rustc_errors::PResult;
|
||||
|
|
@ -22,7 +21,10 @@ pub(crate) fn expand<'cx>(
|
|||
ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
|
||||
}
|
||||
|
||||
fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
|
||||
fn parse_pat_ty<'a>(
|
||||
cx: &mut ExtCtxt<'a>,
|
||||
stream: TokenStream,
|
||||
) -> PResult<'a, (Box<Ty>, Box<TyPat>)> {
|
||||
let mut parser = cx.new_parser_from_tts(stream);
|
||||
|
||||
let ty = parser.parse_ty()?;
|
||||
|
|
@ -45,15 +47,15 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P
|
|||
Ok((ty, pat))
|
||||
}
|
||||
|
||||
fn ty_pat(kind: TyPatKind, span: Span) -> P<TyPat> {
|
||||
P(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
|
||||
fn ty_pat(kind: TyPatKind, span: Span) -> Box<TyPat> {
|
||||
Box::new(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
|
||||
}
|
||||
|
||||
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> P<TyPat> {
|
||||
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> Box<TyPat> {
|
||||
let kind = match pat.kind {
|
||||
ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
|
||||
start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
end.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
include_end,
|
||||
),
|
||||
ast::PatKind::Or(variants) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{mem, slice};
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::{self as ast, HasNodeId, NodeId, attr};
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
|
@ -286,7 +285,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
// // ...
|
||||
// ];
|
||||
// }
|
||||
fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
|
||||
fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
|
||||
let expn_id = cx.resolver.expansion_for_ast_pass(
|
||||
DUMMY_SP,
|
||||
AstPass::ProcMacroHarness,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{join_path_idents, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
|
@ -144,7 +143,7 @@ pub(crate) fn expand_include<'cx>(
|
|||
node_id: ast::NodeId,
|
||||
}
|
||||
impl<'a> MacResult for ExpandInclude<'a> {
|
||||
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<P<ast::Expr>> {
|
||||
fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
|
||||
let expr = parse_expr(&mut self.p).ok()?;
|
||||
if self.p.token != token::Eof {
|
||||
self.p.psess.buffer_lint(
|
||||
|
|
@ -157,7 +156,7 @@ pub(crate) fn expand_include<'cx>(
|
|||
Some(expr)
|
||||
}
|
||||
|
||||
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
|
||||
fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
|
||||
let mut ret = SmallVec::new();
|
||||
loop {
|
||||
match self.p.parse_item(ForceCollect::No) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::iter;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr, join_path_idents};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
|
|
@ -78,7 +77,7 @@ pub(crate) fn expand_test_case(
|
|||
}
|
||||
|
||||
let ret = if is_stmt {
|
||||
Annotatable::Stmt(P(ecx.stmt_item(item.span, item)))
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(item.span, item)))
|
||||
} else {
|
||||
Annotatable::Item(item)
|
||||
};
|
||||
|
|
@ -131,7 +130,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
let ast::ItemKind::Fn(fn_) = &item.kind else {
|
||||
not_testable_error(cx, attr_sp, Some(&item));
|
||||
return if is_stmt {
|
||||
vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
|
||||
vec![Annotatable::Stmt(Box::new(cx.stmt_item(item.span, item)))]
|
||||
} else {
|
||||
vec![Annotatable::Item(item)]
|
||||
};
|
||||
|
|
@ -155,7 +154,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
};
|
||||
if check_result.is_err() {
|
||||
return if is_stmt {
|
||||
vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
|
||||
vec![Annotatable::Stmt(Box::new(cx.stmt_item(item.span, item)))]
|
||||
} else {
|
||||
vec![Annotatable::Item(item)]
|
||||
};
|
||||
|
|
@ -201,7 +200,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
// `-Cinstrument-coverage` builds.
|
||||
// This requires `#[allow_internal_unstable(coverage_attribute)]` on the
|
||||
// corresponding macro declaration in `core::macros`.
|
||||
let coverage_off = |mut expr: P<ast::Expr>| {
|
||||
let coverage_off = |mut expr: Box<ast::Expr>| {
|
||||
assert_matches!(expr.kind, ast::ExprKind::Closure(_));
|
||||
expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp));
|
||||
expr
|
||||
|
|
@ -388,11 +387,11 @@ pub(crate) fn expand_test_or_bench(
|
|||
if is_stmt {
|
||||
vec![
|
||||
// Access to libtest under a hygienic name
|
||||
Annotatable::Stmt(P(cx.stmt_item(sp, test_extern))),
|
||||
Annotatable::Stmt(Box::new(cx.stmt_item(sp, test_extern))),
|
||||
// The generated test case
|
||||
Annotatable::Stmt(P(cx.stmt_item(sp, test_const))),
|
||||
Annotatable::Stmt(Box::new(cx.stmt_item(sp, test_const))),
|
||||
// The original item
|
||||
Annotatable::Stmt(P(cx.stmt_item(sp, item))),
|
||||
Annotatable::Stmt(Box::new(cx.stmt_item(sp, item))),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use std::mem;
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::entry::EntryPointType;
|
||||
use rustc_ast::mut_visit::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::{ModKind, attr};
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
|
|
@ -284,7 +283,7 @@ fn generate_test_harness(
|
|||
/// [`TestCtxt::reexport_test_harness_main`] provides a different name for the `main`
|
||||
/// function and [`TestCtxt::test_runner`] provides a path that replaces
|
||||
/// `test::test_main_static`.
|
||||
fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
||||
fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
|
||||
let sp = cx.def_site;
|
||||
let ecx = &cx.ext_cx;
|
||||
let test_ident = Ident::new(sym::test, sp);
|
||||
|
|
@ -348,7 +347,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
|||
define_opaque: None,
|
||||
}));
|
||||
|
||||
let main = P(ast::Item {
|
||||
let main = Box::new(ast::Item {
|
||||
attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: main,
|
||||
|
|
@ -364,7 +363,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
|||
|
||||
/// Creates a slice containing every test like so:
|
||||
/// &[&test1, &test2]
|
||||
fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
|
||||
fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
|
||||
debug!("building test vector from {} tests", cx.test_cases.len());
|
||||
let ecx = &cx.ext_cx;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{self as ast, AttrStyle, Attribute, MetaItem, attr, token};
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
||||
|
|
@ -83,7 +82,7 @@ type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), Err
|
|||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(crate) fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
expr: Box<ast::Expr>,
|
||||
err_msg: &'static str,
|
||||
) -> ExpandResult<ExprToSpannedStringResult<'a>, ()> {
|
||||
if !cx.force_mode
|
||||
|
|
@ -135,7 +134,7 @@ pub(crate) fn expr_to_spanned_string<'a>(
|
|||
/// compilation on error, merely emits a non-fatal error and returns `Err`.
|
||||
pub(crate) fn expr_to_string(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
expr: P<ast::Expr>,
|
||||
expr: Box<ast::Expr>,
|
||||
err_msg: &'static str,
|
||||
) -> ExpandResult<Result<(Symbol, ast::StrStyle), ErrorGuaranteed>, ()> {
|
||||
expr_to_spanned_string(cx, expr, err_msg).map(|res| {
|
||||
|
|
@ -158,7 +157,7 @@ pub(crate) fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, nam
|
|||
}
|
||||
|
||||
/// Parse an expression. On error, emit it, advancing to `Eof`, and return `Err`.
|
||||
pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result<P<ast::Expr>, ErrorGuaranteed> {
|
||||
pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result<Box<ast::Expr>, ErrorGuaranteed> {
|
||||
let guar = match p.parse_expr() {
|
||||
Ok(expr) => return Ok(expr),
|
||||
Err(err) => err.emit(),
|
||||
|
|
@ -209,7 +208,7 @@ pub(crate) fn get_single_expr_from_tts(
|
|||
span: Span,
|
||||
tts: TokenStream,
|
||||
name: &str,
|
||||
) -> ExpandResult<Result<P<ast::Expr>, ErrorGuaranteed>, ()> {
|
||||
) -> ExpandResult<Result<Box<ast::Expr>, ErrorGuaranteed>, ()> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
if p.token == token::Eof {
|
||||
let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
|
||||
|
|
@ -232,7 +231,7 @@ pub(crate) fn get_single_expr_from_tts(
|
|||
pub(crate) fn get_exprs_from_tts(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
tts: TokenStream,
|
||||
) -> ExpandResult<Result<Vec<P<ast::Expr>>, ErrorGuaranteed>, ()> {
|
||||
) -> ExpandResult<Result<Vec<Box<ast::Expr>>, ErrorGuaranteed>, ()> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
let mut es = Vec::new();
|
||||
while p.token != token::Eof {
|
||||
|
|
|
|||
|
|
@ -557,13 +557,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
let (size, signed) = ty.int_size_and_signed(self.tcx);
|
||||
let width = size.bits();
|
||||
|
||||
if oop == OverflowOp::Sub && !signed {
|
||||
// Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
|
||||
// to be the canonical form. It will attempt to reform llvm.usub.with.overflow
|
||||
// in the backend if profitable.
|
||||
let sub = self.sub(lhs, rhs);
|
||||
let cmp = self.icmp(IntPredicate::IntULT, lhs, rhs);
|
||||
return (sub, cmp);
|
||||
if !signed {
|
||||
match oop {
|
||||
OverflowOp::Sub => {
|
||||
// Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
|
||||
// to be the canonical form. It will attempt to reform llvm.usub.with.overflow
|
||||
// in the backend if profitable.
|
||||
let sub = self.sub(lhs, rhs);
|
||||
let cmp = self.icmp(IntPredicate::IntULT, lhs, rhs);
|
||||
return (sub, cmp);
|
||||
}
|
||||
OverflowOp::Add => {
|
||||
// Like with sub above, using icmp is the preferred form. See
|
||||
// <https://rust-lang.zulipchat.com/#narrow/channel/187780-t-compiler.2Fllvm/topic/.60uadd.2Ewith.2Eoverflow.60.20.28again.29/near/533041085>
|
||||
let add = self.add(lhs, rhs);
|
||||
let cmp = self.icmp(IntPredicate::IntULT, add, lhs);
|
||||
return (add, cmp);
|
||||
}
|
||||
OverflowOp::Mul => {}
|
||||
}
|
||||
}
|
||||
|
||||
let oop_str = match oop {
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented y
|
|||
|
||||
codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
|
||||
|
||||
codegen_ssa_link_exe_status_stack_buffer_overrun = 0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`
|
||||
.abort_note = this may have been caused by a program abort and not a stack buffer overrun
|
||||
.event_log_note = consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code
|
||||
|
||||
codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
|
||||
|
||||
codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
|
||||
|
|
@ -397,6 +401,9 @@ codegen_ssa_version_script_write_failure = failed to write version script: {$err
|
|||
|
||||
codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
|
||||
|
||||
codegen_ssa_xcrun_about =
|
||||
the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file
|
||||
|
||||
codegen_ssa_xcrun_command_line_tools_insufficient =
|
||||
when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,10 @@ pub(super) fn add_version_to_llvm_target(
|
|||
pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
|
||||
let sdk_name = sdk_name(&sess.target);
|
||||
|
||||
// Attempt to invoke `xcrun` to find the SDK.
|
||||
//
|
||||
// Note that when cross-compiling from e.g. Linux, the `xcrun` binary may sometimes be provided
|
||||
// as a shim by a cross-compilation helper tool. It usually isn't, but we still try nonetheless.
|
||||
match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
|
||||
Ok((path, stderr)) => {
|
||||
// Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
|
||||
|
|
@ -169,7 +173,19 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
|
|||
Some(path)
|
||||
}
|
||||
Err(err) => {
|
||||
let mut diag = sess.dcx().create_err(err);
|
||||
// Failure to find the SDK is not a hard error, since the user might have specified it
|
||||
// in a manner unknown to us (moreso if cross-compiling):
|
||||
// - A compiler driver like `zig cc` which links using an internally bundled SDK.
|
||||
// - Extra linker arguments (`-Clink-arg=-syslibroot`).
|
||||
// - A custom linker or custom compiler driver.
|
||||
//
|
||||
// Though we still warn, since such cases are uncommon, and it is very hard to debug if
|
||||
// you do not know the details.
|
||||
//
|
||||
// FIXME(madsmtm): Make this a lint, to allow deny warnings to work.
|
||||
// (Or fix <https://github.com/rust-lang/rust/issues/21204>).
|
||||
let mut diag = sess.dcx().create_warn(err);
|
||||
diag.note(fluent::codegen_ssa_xcrun_about);
|
||||
|
||||
// Recognize common error cases, and give more Rust-specific error messages for those.
|
||||
if let Some(developer_dir) = xcode_select_developer_dir() {
|
||||
|
|
@ -209,6 +225,8 @@ fn xcrun_show_sdk_path(
|
|||
sdk_name: &'static str,
|
||||
verbose: bool,
|
||||
) -> Result<(PathBuf, String), XcrunError> {
|
||||
// Intentionally invoke the `xcrun` in PATH, since e.g. nixpkgs provide an `xcrun` shim, so we
|
||||
// don't want to require `/usr/bin/xcrun`.
|
||||
let mut cmd = Command::new("xcrun");
|
||||
if verbose {
|
||||
cmd.arg("--verbose");
|
||||
|
|
@ -280,7 +298,7 @@ fn stdout_to_path(mut stdout: Vec<u8>) -> PathBuf {
|
|||
}
|
||||
#[cfg(unix)]
|
||||
let path = <OsString as std::os::unix::ffi::OsStringExt>::from_vec(stdout);
|
||||
#[cfg(not(unix))] // Unimportant, this is only used on macOS
|
||||
let path = OsString::from(String::from_utf8(stdout).unwrap());
|
||||
#[cfg(not(unix))] // Not so important, this is mostly used on macOS
|
||||
let path = OsString::from(String::from_utf8(stdout).expect("stdout must be UTF-8"));
|
||||
PathBuf::from(path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -880,6 +880,14 @@ fn link_natively(
|
|||
windows_registry::find_tool(&sess.target.arch, "link.exe").is_some();
|
||||
|
||||
sess.dcx().emit_note(errors::LinkExeUnexpectedError);
|
||||
|
||||
// STATUS_STACK_BUFFER_OVERRUN is also used for fast abnormal program termination, e.g. abort().
|
||||
// Emit a special diagnostic to let people know that this most likely doesn't indicate a stack buffer overrun.
|
||||
const STATUS_STACK_BUFFER_OVERRUN: i32 = 0xc0000409u32 as _;
|
||||
if code == STATUS_STACK_BUFFER_OVERRUN {
|
||||
sess.dcx().emit_note(errors::LinkExeStatusStackBufferOverrun);
|
||||
}
|
||||
|
||||
if is_vs_installed && has_linker {
|
||||
// the linker is broken
|
||||
sess.dcx().emit_note(errors::RepairVSBuildTools);
|
||||
|
|
@ -3186,39 +3194,60 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
|
|||
}
|
||||
|
||||
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
|
||||
let os = &sess.target.os;
|
||||
if sess.target.vendor != "apple"
|
||||
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
|
||||
|| !matches!(flavor, LinkerFlavor::Darwin(..))
|
||||
{
|
||||
if !sess.target.is_like_darwin {
|
||||
return None;
|
||||
}
|
||||
|
||||
if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) {
|
||||
let LinkerFlavor::Darwin(cc, _) = flavor else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// The default compiler driver on macOS is at `/usr/bin/cc`. This is a trampoline binary that
|
||||
// effectively invokes `xcrun cc` internally to look up both the compiler binary and the SDK
|
||||
// root from the current Xcode installation. When cross-compiling, when `rustc` is invoked
|
||||
// inside Xcode, or when invoking the linker directly, this default logic is unsuitable, so
|
||||
// instead we invoke `xcrun` manually.
|
||||
//
|
||||
// (Note that this doesn't mean we get a duplicate lookup here - passing `SDKROOT` below will
|
||||
// cause the trampoline binary to skip looking up the SDK itself).
|
||||
let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
|
||||
|
||||
if cc == Cc::Yes {
|
||||
// There are a few options to pass the SDK root when linking with a C/C++ compiler:
|
||||
// - The `--sysroot` flag.
|
||||
// - The `-isysroot` flag.
|
||||
// - The `SDKROOT` environment variable.
|
||||
//
|
||||
// `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need
|
||||
// to specify `-isysroot`. This is admittedly a bit strange, as on most targets `-isysroot`
|
||||
// only applies to include header files, but on Apple targets it also applies to libraries
|
||||
// and frameworks.
|
||||
//
|
||||
// This leaves the choice between `-isysroot` and `SDKROOT`. Both are supported by Clang and
|
||||
// GCC, though they may not be supported by all compiler drivers. We choose `SDKROOT`,
|
||||
// primarily because that is the same interface that is used when invoking the tool under
|
||||
// `xcrun -sdk macosx $tool`.
|
||||
//
|
||||
// In that sense, if a given compiler driver does not support `SDKROOT`, the blame is fairly
|
||||
// clearly in the tool in question, since they also don't support being run under `xcrun`.
|
||||
//
|
||||
// Additionally, `SDKROOT` is an environment variable and thus optional. It also has lower
|
||||
// precedence than `-isysroot`, so a custom compiler driver that does not support it and
|
||||
// instead figures out the SDK on their own can easily do so by using `-isysroot`.
|
||||
//
|
||||
// (This in particular affects Clang built with the `DEFAULT_SYSROOT` CMake flag, such as
|
||||
// the one provided by some versions of Homebrew's `llvm` package. Those will end up
|
||||
// ignoring the value we set here, and instead use their built-in sysroot).
|
||||
cmd.cmd().env("SDKROOT", &sdkroot);
|
||||
} else {
|
||||
// When invoking the linker directly, we use the `-syslibroot` parameter. `SDKROOT` is not
|
||||
// read by the linker, so it's really the only option.
|
||||
//
|
||||
// This is also what Clang does.
|
||||
cmd.link_arg("-syslibroot");
|
||||
cmd.link_arg(&sdkroot);
|
||||
}
|
||||
|
||||
let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
|
||||
|
||||
match flavor {
|
||||
LinkerFlavor::Darwin(Cc::Yes, _) => {
|
||||
// Use `-isysroot` instead of `--sysroot`, as only the former
|
||||
// makes Clang treat it as a platform SDK.
|
||||
//
|
||||
// This is admittedly a bit strange, as on most targets
|
||||
// `-isysroot` only applies to include header files, but on Apple
|
||||
// targets this also applies to libraries and frameworks.
|
||||
cmd.cc_arg("-isysroot");
|
||||
cmd.cc_arg(&sdk_root);
|
||||
}
|
||||
LinkerFlavor::Darwin(Cc::No, _) => {
|
||||
cmd.link_arg("-syslibroot");
|
||||
cmd.link_arg(&sdk_root);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Some(sdk_root)
|
||||
Some(sdkroot)
|
||||
}
|
||||
|
||||
fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
|
||||
|
|
@ -3247,7 +3276,13 @@ fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
|
|||
}
|
||||
"macosx"
|
||||
if sdkroot.contains("iPhoneOS.platform")
|
||||
|| sdkroot.contains("iPhoneSimulator.platform") => {}
|
||||
|| sdkroot.contains("iPhoneSimulator.platform")
|
||||
|| sdkroot.contains("AppleTVOS.platform")
|
||||
|| sdkroot.contains("AppleTVSimulator.platform")
|
||||
|| sdkroot.contains("WatchOS.platform")
|
||||
|| sdkroot.contains("WatchSimulator.platform")
|
||||
|| sdkroot.contains("XROS.platform")
|
||||
|| sdkroot.contains("XRSimulator.platform") => {}
|
||||
"watchos"
|
||||
if sdkroot.contains("WatchSimulator.platform")
|
||||
|| sdkroot.contains("MacOSX.platform") => {}
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
|
|||
// core/std/allocators/etc. For example symbols used to hook up allocation
|
||||
// are not considered for export
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
|
||||
let is_extern = codegen_fn_attrs.contains_extern_indicator();
|
||||
let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
|
||||
let std_internal =
|
||||
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
|
||||
|
|
|
|||
|
|
@ -443,6 +443,27 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
|
|||
if tcx.should_inherit_track_caller(did) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
}
|
||||
|
||||
// Foreign items by default use no mangling for their symbol name.
|
||||
if tcx.is_foreign_item(did) {
|
||||
// There's a few exceptions to this rule though:
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
||||
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
|
||||
// both for exports and imports through foreign items. This is handled further,
|
||||
// during symbol mangling logic.
|
||||
} else if codegen_fn_attrs.link_name.is_some() {
|
||||
// * This can be overridden with the `#[link_name]` attribute
|
||||
} else {
|
||||
// NOTE: there's one more exception that we cannot apply here. On wasm,
|
||||
// some items cannot be `no_mangle`.
|
||||
// However, we don't have enough information here to determine that.
|
||||
// As such, no_mangle foreign items on wasm that have the same defid as some
|
||||
// import will *still* be mangled despite this.
|
||||
//
|
||||
// if none of the exceptions apply; apply no_mangle
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_result(
|
||||
|
|
|
|||
|
|
@ -550,6 +550,18 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
|||
#[diag(codegen_ssa_link_exe_unexpected_error)]
|
||||
pub(crate) struct LinkExeUnexpectedError;
|
||||
|
||||
pub(crate) struct LinkExeStatusStackBufferOverrun;
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun {
|
||||
fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let mut diag =
|
||||
Diag::new(dcx, level, fluent::codegen_ssa_link_exe_status_stack_buffer_overrun);
|
||||
diag.note(fluent::codegen_ssa_abort_note);
|
||||
diag.note(fluent::codegen_ssa_event_log_note);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_repair_vs_build_tools)]
|
||||
pub(crate) struct RepairVSBuildTools;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue