Auto merge of #3711 - saethlin:rustup, r=saethlin
Manual Rustup This bumps us to a rustc commit that doesn't have the chatty `./miri fmt` reported in https://rust-lang.zulipchat.com/#narrow/stream/269128-miri/topic/.22rewriting.20static.22.20printed.20during.20.2E.2Fmiri.20build
This commit is contained in:
commit
fc94ce216e
901 changed files with 8273 additions and 7046 deletions
|
|
@ -427,11 +427,13 @@ pub struct Size {
|
|||
raw: u64,
|
||||
}
|
||||
|
||||
// Safety: Ord is implement as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
#[cfg(feature = "nightly")]
|
||||
unsafe impl StableOrd for Size {
|
||||
impl StableOrd for Size {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// `Ord` is implemented as just comparing numerical values and numerical values
|
||||
// are not changed by (de-)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
// This is debug-printed a lot in larger structs, don't waste too much space there
|
||||
|
|
|
|||
|
|
@ -429,10 +429,10 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
|
|||
) -> SmallVec<[PatField; 1]> {
|
||||
let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
smallvec![fp]
|
||||
}
|
||||
|
||||
|
|
@ -443,8 +443,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
|
|||
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
|
||||
UseTreeKind::Nested { items, .. } => {
|
||||
for (tree, id) in items {
|
||||
vis.visit_use_tree(tree);
|
||||
vis.visit_id(id);
|
||||
vis.visit_use_tree(tree);
|
||||
}
|
||||
}
|
||||
UseTreeKind::Glob => {}
|
||||
|
|
@ -454,8 +454,8 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
|
|||
|
||||
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
|
||||
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(guard, |guard| vis.visit_expr(guard));
|
||||
visit_opt(body, |body| vis.visit_expr(body));
|
||||
|
|
@ -548,10 +548,10 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
|
|||
visitor: &mut T,
|
||||
) -> SmallVec<[Variant; 1]> {
|
||||
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
|
||||
visitor.visit_id(id);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_ident(ident);
|
||||
visitor.visit_vis(vis);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_variant_data(data);
|
||||
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
|
||||
visitor.visit_span(span);
|
||||
|
|
@ -565,8 +565,8 @@ fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mu
|
|||
fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
for PathSegment { ident, id, args } in segments {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(args, |args| vis.visit_generic_args(args));
|
||||
}
|
||||
visit_lazy_tts(tokens, vis);
|
||||
|
|
@ -620,6 +620,7 @@ fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
|
|||
fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||
let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
match kind {
|
||||
|
|
@ -634,7 +635,6 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
|||
}
|
||||
vis.visit_span(span);
|
||||
visit_opt(colon_sp, |sp| vis.visit_span(sp));
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
}
|
||||
|
||||
|
|
@ -894,9 +894,9 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
|
|||
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
|
||||
| CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
|
||||
| CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
|
||||
vis.visit_span(span);
|
||||
vis.visit_id(closure_id);
|
||||
vis.visit_id(return_impl_trait_id);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -932,8 +932,8 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
|
|||
vis.visit_lifetime(lt);
|
||||
}
|
||||
PreciseCapturingArg::Arg(path, id) => {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -944,11 +944,11 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
|||
) -> SmallVec<[GenericParam; 1]> {
|
||||
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
if let Some(colon_span) = colon_span {
|
||||
vis.visit_span(colon_span);
|
||||
}
|
||||
visit_attrs(attrs, vis);
|
||||
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
|
||||
match kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
|
|
@ -1015,16 +1015,16 @@ fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T)
|
|||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Tuple(fields, id) => {
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
vis.visit_id(id);
|
||||
fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
|
||||
}
|
||||
VariantData::Unit(id) => vis.visit_id(id),
|
||||
}
|
||||
}
|
||||
|
||||
fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(ref_id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
|
||||
fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
|
||||
|
|
@ -1039,12 +1039,12 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
|
|||
visitor: &mut T,
|
||||
) -> SmallVec<[FieldDef; 1]> {
|
||||
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
|
||||
visitor.visit_id(id);
|
||||
visit_attrs(attrs, visitor);
|
||||
visitor.visit_span(span);
|
||||
visit_opt(ident, |ident| visitor.visit_ident(ident));
|
||||
visitor.visit_vis(vis);
|
||||
visitor.visit_id(id);
|
||||
visitor.visit_ty(ty);
|
||||
visit_attrs(attrs, visitor);
|
||||
smallvec![fd]
|
||||
}
|
||||
|
||||
|
|
@ -1053,11 +1053,11 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
|
|||
vis: &mut T,
|
||||
) -> SmallVec<[ExprField; 1]> {
|
||||
let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_id(id);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
smallvec![f]
|
||||
}
|
||||
|
||||
|
|
@ -1429,6 +1429,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
Expr { kind, id, span, attrs, tokens }: &mut Expr,
|
||||
vis: &mut T,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
match kind {
|
||||
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
||||
ExprKind::ConstBlock(anon_const) => {
|
||||
|
|
@ -1449,8 +1451,8 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
args: call_args,
|
||||
span,
|
||||
}) => {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
visit_opt(seg_args, |args| vis.visit_generic_args(args));
|
||||
vis.visit_method_receiver_expr(receiver);
|
||||
visit_thin_exprs(call_args, vis);
|
||||
|
|
@ -1601,9 +1603,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||
ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {}
|
||||
}
|
||||
vis.visit_id(id);
|
||||
vis.visit_span(span);
|
||||
visit_attrs(attrs, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
}
|
||||
|
||||
|
|
@ -1645,8 +1645,8 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
|
|||
StmtKind::Empty => smallvec![StmtKind::Empty],
|
||||
StmtKind::MacCall(mut mac) => {
|
||||
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
|
||||
vis.visit_mac_call(mac_);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_mac_call(mac_);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
smallvec![StmtKind::MacCall(mac)]
|
||||
}
|
||||
|
|
@ -1657,8 +1657,8 @@ fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
|
|||
match &mut visibility.kind {
|
||||
VisibilityKind::Public | VisibilityKind::Inherited => {}
|
||||
VisibilityKind::Restricted { path, id, shorthand: _ } => {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(id);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
}
|
||||
vis.visit_span(&mut visibility.span);
|
||||
|
|
|
|||
|
|
@ -298,8 +298,8 @@ pub trait Visitor<'ast>: Sized {
|
|||
}
|
||||
|
||||
pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
|
||||
walk_list!(visitor, visit_item, &krate.items);
|
||||
walk_list!(visitor, visit_attribute, &krate.attrs);
|
||||
walk_list!(visitor, visit_item, &krate.items);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
|
@ -462,25 +462,25 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -
|
|||
where
|
||||
V: Visitor<'a>,
|
||||
{
|
||||
walk_list!(visitor, visit_attribute, &variant.attrs);
|
||||
try_visit!(visitor.visit_ident(variant.ident));
|
||||
try_visit!(visitor.visit_vis(&variant.vis));
|
||||
try_visit!(visitor.visit_variant_data(&variant.data));
|
||||
visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
|
||||
walk_list!(visitor, visit_attribute, &variant.attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &f.attrs);
|
||||
try_visit!(visitor.visit_expr(&f.expr));
|
||||
try_visit!(visitor.visit_ident(f.ident));
|
||||
walk_list!(visitor, visit_attribute, &f.attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &fp.attrs);
|
||||
try_visit!(visitor.visit_ident(fp.ident));
|
||||
try_visit!(visitor.visit_pat(&fp.pat));
|
||||
walk_list!(visitor, visit_attribute, &fp.attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
|
@ -722,8 +722,8 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(
|
|||
visitor: &mut V,
|
||||
param: &'a GenericParam,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_ident(param.ident));
|
||||
walk_list!(visitor, visit_attribute, ¶m.attrs);
|
||||
try_visit!(visitor.visit_ident(param.ident));
|
||||
walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound);
|
||||
match ¶m.kind {
|
||||
GenericParamKind::Lifetime => (),
|
||||
|
|
@ -882,10 +882,10 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
|
|||
ctxt: AssocCtxt,
|
||||
) -> V::Result {
|
||||
let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_vis(vis));
|
||||
try_visit!(visitor.visit_ident(ident));
|
||||
try_visit!(kind.walk(item, ctxt, visitor));
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
|
@ -898,10 +898,10 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(
|
|||
}
|
||||
|
||||
pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &field.attrs);
|
||||
try_visit!(visitor.visit_vis(&field.vis));
|
||||
visit_opt!(visitor, visit_ident, field.ident);
|
||||
try_visit!(visitor.visit_ty(&field.ty));
|
||||
walk_list!(visitor, visit_attribute, &field.attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
|
@ -918,8 +918,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V:
|
|||
StmtKind::Empty => {}
|
||||
StmtKind::MacCall(mac) => {
|
||||
let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
|
||||
try_visit!(visitor.visit_mac_call(mac));
|
||||
walk_list!(visitor, visit_attribute, attrs);
|
||||
try_visit!(visitor.visit_mac_call(mac));
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
|
|
@ -1141,10 +1141,10 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::R
|
|||
}
|
||||
|
||||
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
|
||||
walk_list!(visitor, visit_attribute, &arm.attrs);
|
||||
try_visit!(visitor.visit_pat(&arm.pat));
|
||||
visit_opt!(visitor, visit_expr, &arm.guard);
|
||||
visit_opt!(visitor, visit_expr, &arm.body);
|
||||
walk_list!(visitor, visit_attribute, &arm.attrs);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_middle::span_bug;
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> crate::MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
|
||||
self.infcx.dcx()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
|||
|
||||
pub(crate) fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
error_element: RegionElement,
|
||||
cause: ObligationCause<'tcx>,
|
||||
|
|
@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> {
|
|||
|
||||
fn nice_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
|
|
@ -160,7 +160,7 @@ trait TypeOpInfo<'tcx> {
|
|||
#[instrument(level = "debug", skip(self, mbcx))]
|
||||
fn report_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
error_element: RegionElement,
|
||||
cause: ObligationCause<'tcx>,
|
||||
|
|
@ -233,7 +233,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
|
|||
|
||||
fn nice_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
|
|
@ -270,7 +270,7 @@ where
|
|||
|
||||
fn nice_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
|
|
@ -310,7 +310,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
|
|||
|
||||
fn nice_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
|
|
@ -336,7 +336,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
|
|||
|
||||
fn nice_error(
|
||||
&self,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
|
||||
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
_cause: ObligationCause<'tcx>,
|
||||
placeholder_region: ty::Region<'tcx>,
|
||||
error_region: Option<ty::Region<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ enum StorageDeadOrDrop<'tcx> {
|
|||
Destructor(Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub(crate) fn report_use_of_moved_or_uninitialized(
|
||||
&mut self,
|
||||
location: Location,
|
||||
|
|
@ -4243,7 +4243,11 @@ enum AnnotatedBorrowFnSignature<'tcx> {
|
|||
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
|
||||
/// Annotate the provided diagnostic with information about borrow from the fn signature that
|
||||
/// helps explain.
|
||||
pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diag<'_>) -> String {
|
||||
pub(crate) fn emit(
|
||||
&self,
|
||||
cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>,
|
||||
diag: &mut Diag<'_>,
|
||||
) -> String {
|
||||
match self {
|
||||
&AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
|
||||
diag.span_label(
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
fn free_region_constraint_info(
|
||||
&self,
|
||||
borrow_region: RegionVid,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ pub(super) struct DescribePlaceOpt {
|
|||
|
||||
pub(super) struct IncludingTupleField(pub(super) bool);
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
|
||||
/// is moved after being invoked.
|
||||
///
|
||||
|
|
@ -771,7 +771,7 @@ struct CapturedMessageOpt {
|
|||
maybe_reinitialized_locations_is_empty: bool,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub(crate) fn report_move_errors(&mut self) {
|
||||
let grouped_errors = self.group_move_errors();
|
||||
for error in grouped_errors {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub(crate) enum AccessKind {
|
|||
Mutate,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub(crate) fn report_mutability_error(
|
||||
&mut self,
|
||||
access_place: Place<'tcx>,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl OutlivesSuggestionBuilder {
|
|||
/// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
|
||||
fn region_vid_to_name(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
region: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
|
||||
|
|
@ -84,7 +84,7 @@ impl OutlivesSuggestionBuilder {
|
|||
/// Compiles a list of all suggestions to be printed in the final big suggestion.
|
||||
fn compile_all_suggestions(
|
||||
&self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
) -> SmallVec<[SuggestedConstraint; 2]> {
|
||||
let mut suggested = SmallVec::new();
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ impl OutlivesSuggestionBuilder {
|
|||
/// Emit an intermediate note on the given `Diag` if the involved regions are suggestable.
|
||||
pub(crate) fn intermediate_suggestion(
|
||||
&mut self,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||
mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
|
||||
errci: &ErrorConstraintInfo<'_>,
|
||||
diag: &mut Diag<'_>,
|
||||
) {
|
||||
|
|
@ -179,7 +179,7 @@ impl OutlivesSuggestionBuilder {
|
|||
|
||||
/// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
|
||||
/// suggestion including all collected constraints.
|
||||
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
|
||||
pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) {
|
||||
// No constraints to add? Done.
|
||||
if self.constraints_to_add.is_empty() {
|
||||
debug!("No constraints to suggest.");
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ pub struct ErrorConstraintInfo<'tcx> {
|
|||
pub(super) span: Span,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Converts a region inference variable into a `ty::Region` that
|
||||
/// we can use for error reporting. If `r` is universally bound,
|
||||
/// then we use the name that we have on record for it. If `r` is
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ impl rustc_errors::IntoDiagArg for RegionName {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
|
||||
self.body.source.def_id().expect_local()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,11 +310,11 @@ fn do_mir_borrowck<'tcx>(
|
|||
promoted_mbcx.report_move_errors();
|
||||
diags = promoted_mbcx.diags;
|
||||
|
||||
struct MoveVisitor<'a, 'cx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
struct MoveVisitor<'a, 'b, 'mir, 'cx, 'tcx> {
|
||||
ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'cx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
|
||||
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
if let Operand::Move(place) = operand {
|
||||
self.ctxt.check_movable_place(location, *place);
|
||||
|
|
@ -528,15 +528,15 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
struct MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx> {
|
||||
infcx: &'cx BorrowckInferCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
body: &'cx Body<'tcx>,
|
||||
move_data: &'cx MoveData<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
|
||||
/// Map from MIR `Location` to `LocationIndex`; created
|
||||
/// when MIR borrowck begins.
|
||||
location_table: &'cx LocationTable,
|
||||
location_table: &'a LocationTable,
|
||||
|
||||
movable_coroutine: bool,
|
||||
/// This keeps track of whether local variables are free-ed when the function
|
||||
|
|
@ -605,14 +605,16 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
|||
// 2. loans made in overlapping scopes do not conflict
|
||||
// 3. assignments do not affect things loaned out as immutable
|
||||
// 4. moves do not affect things loaned out in any way
|
||||
impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
|
||||
type FlowState = Flows<'cx, 'tcx>;
|
||||
impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
||||
for MirBorrowckCtxt<'_, 'mir, '_, 'tcx>
|
||||
{
|
||||
type FlowState = Flows<'mir, 'tcx>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
stmt: &'cx Statement<'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
stmt: &'mir Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state);
|
||||
|
|
@ -681,8 +683,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
|||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state);
|
||||
|
|
@ -792,8 +794,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
|
|||
fn visit_terminator_after_primary_effect(
|
||||
&mut self,
|
||||
_results: &mut R,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
term: &'cx Terminator<'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
term: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
let span = term.source_info.span;
|
||||
|
|
@ -969,8 +971,8 @@ impl InitializationRequiringAction {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn body(&self) -> &'cx Body<'tcx> {
|
||||
impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
||||
fn body(&self) -> &'mir Body<'tcx> {
|
||||
self.body
|
||||
}
|
||||
|
||||
|
|
@ -986,7 +988,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
place_span: (Place<'tcx>, Span),
|
||||
kind: (AccessDepth, ReadOrWrite),
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
let (sd, rw) = kind;
|
||||
|
||||
|
|
@ -1036,7 +1038,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
place_span: (Place<'tcx>, Span),
|
||||
sd: AccessDepth,
|
||||
rw: ReadOrWrite,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) -> bool {
|
||||
let mut error_reported = false;
|
||||
let borrow_set = Rc::clone(&self.borrow_set);
|
||||
|
|
@ -1177,7 +1179,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
location: Location,
|
||||
place_span: (Place<'tcx>, Span),
|
||||
kind: AccessDepth,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
// Write of P[i] or *P requires P init'd.
|
||||
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
|
||||
|
|
@ -1194,8 +1196,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn consume_rvalue(
|
||||
&mut self,
|
||||
location: Location,
|
||||
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
(rvalue, span): (&'mir Rvalue<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
match rvalue {
|
||||
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
|
||||
|
|
@ -1452,8 +1454,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn consume_operand(
|
||||
&mut self,
|
||||
location: Location,
|
||||
(operand, span): (&'cx Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
(operand, span): (&'mir Operand<'tcx>, Span),
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
match *operand {
|
||||
Operand::Copy(place) => {
|
||||
|
|
@ -1573,7 +1575,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'cx, 'tcx>) {
|
||||
fn check_activations(
|
||||
&mut self,
|
||||
location: Location,
|
||||
span: Span,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
// Two-phase borrow support: For each activation that is newly
|
||||
// generated at this statement, check if it interferes with
|
||||
// another borrow.
|
||||
|
|
@ -1736,7 +1743,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
|
|
@ -1841,7 +1848,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
|
||||
|
|
@ -1940,7 +1947,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&mut self,
|
||||
location: Location,
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
debug!("check_if_assigned_path_is_moved place: {:?}", place);
|
||||
|
||||
|
|
@ -2001,12 +2008,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_parent_of_field<'cx, 'tcx>(
|
||||
this: &mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
fn check_parent_of_field<'mir, 'tcx>(
|
||||
this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>,
|
||||
location: Location,
|
||||
base: PlaceRef<'tcx>,
|
||||
span: Span,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) {
|
||||
// rust-lang/rust#21232: Until Rust allows reads from the
|
||||
// initialized parts of partially initialized structs, we
|
||||
|
|
@ -2097,7 +2104,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
(place, span): (Place<'tcx>, Span),
|
||||
kind: ReadOrWrite,
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
debug!(
|
||||
|
|
@ -2213,7 +2220,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn is_local_ever_initialized(
|
||||
&self,
|
||||
local: Local,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
flow_state: &Flows<'mir, 'tcx>,
|
||||
) -> Option<InitIndex> {
|
||||
let mpi = self.move_data.rev_lookup.find_local(local)?;
|
||||
let ii = &self.move_data.init_path_map[mpi];
|
||||
|
|
@ -2221,7 +2228,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'mir, 'tcx>) {
|
||||
match root_place {
|
||||
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
|
||||
// If the local may have been initialized, and it is now currently being
|
||||
|
|
@ -2476,7 +2483,7 @@ mod diags {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
pub fn buffer_error(&mut self, diag: Diag<'tcx>) {
|
||||
self.diags.buffer_error(diag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub(super) enum PrefixSet {
|
|||
Shallow,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Returns an iterator over the prefixes of `place`
|
||||
/// (inclusive) from longest to smallest, potentially
|
||||
/// terminating the iteration early based on `kind`.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_middle::mir::{
|
|||
|
||||
use crate::MirBorrowckCtxt;
|
||||
|
||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
/// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
|
||||
/// of the `unused_mut` lint.
|
||||
///
|
||||
|
|
@ -45,13 +45,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
/// MIR visitor for collecting used mutable variables.
|
||||
/// The 'visit lifetime represents the duration of the MIR walk.
|
||||
struct GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
|
||||
struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'cx, 'tcx> {
|
||||
temporary_used_locals: FxIndexSet<Local>,
|
||||
never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'cx, 'tcx>,
|
||||
}
|
||||
|
||||
impl GatherUsedMutsVisitor<'_, '_, '_> {
|
||||
impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
|
||||
fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
|
||||
// Remove any locals that we found were initialized from the
|
||||
// `never_initialized_mut_locals` set. At the end, the only remaining locals will
|
||||
|
|
@ -63,7 +63,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
|
||||
impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> {
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
debug!("visit_terminator: terminator={:?}", terminator);
|
||||
match &terminator.kind {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ pub(crate) mod decodable;
|
|||
pub(crate) mod default;
|
||||
pub(crate) mod encodable;
|
||||
pub(crate) mod hash;
|
||||
pub(crate) mod smart_ptr;
|
||||
|
||||
#[path = "cmp/eq.rs"]
|
||||
pub(crate) mod eq;
|
||||
|
|
|
|||
140
compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Normal file
140
compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
use std::mem::swap;
|
||||
|
||||
use ast::HasAttrs;
|
||||
use rustc_ast::{
|
||||
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
|
||||
TraitBoundModifiers,
|
||||
};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
macro_rules! path {
|
||||
($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] }
|
||||
}
|
||||
|
||||
pub fn expand_deriving_smart_ptr(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
_mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
_is_const: bool,
|
||||
) {
|
||||
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
|
||||
&& let ItemKind::Struct(_, g) = &aitem.kind
|
||||
{
|
||||
(aitem.ident, g)
|
||||
} else {
|
||||
cx.dcx().struct_span_err(span, "`SmartPointer` can only be derived on `struct`s").emit();
|
||||
return;
|
||||
};
|
||||
|
||||
// Convert generic parameters (from the struct) into generic args.
|
||||
let mut pointee_param = None;
|
||||
let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![];
|
||||
let self_params = generics
|
||||
.params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, p)| match p.kind {
|
||||
GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)),
|
||||
GenericParamKind::Type { .. } => {
|
||||
if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) {
|
||||
if pointee_param.is_some() {
|
||||
multiple_pointee_diag.push(cx.dcx().struct_span_err(
|
||||
p.span(),
|
||||
"`SmartPointer` can only admit one type as pointee",
|
||||
));
|
||||
} else {
|
||||
pointee_param = Some(idx);
|
||||
}
|
||||
}
|
||||
GenericArg::Type(cx.ty_ident(p.span(), p.ident))
|
||||
}
|
||||
GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let Some(pointee_param_idx) = pointee_param else {
|
||||
cx.dcx().struct_span_err(
|
||||
span,
|
||||
"At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits",
|
||||
).emit();
|
||||
return;
|
||||
};
|
||||
if !multiple_pointee_diag.is_empty() {
|
||||
for diag in multiple_pointee_diag {
|
||||
diag.emit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the type of `self`.
|
||||
let path = cx.path_all(span, false, vec![name_ident], self_params.clone());
|
||||
let self_type = cx.ty_path(path);
|
||||
|
||||
// Declare helper function that adds implementation blocks.
|
||||
// FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls
|
||||
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
|
||||
let mut add_impl_block = |generics, trait_symbol, trait_args| {
|
||||
let mut parts = path!(span, core::ops);
|
||||
parts.push(Ident::new(trait_symbol, span));
|
||||
let trait_path = cx.path_all(span, true, parts, trait_args);
|
||||
let trait_ref = cx.trait_ref(trait_path);
|
||||
let item = cx.item(
|
||||
span,
|
||||
Ident::empty(),
|
||||
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,
|
||||
generics,
|
||||
of_trait: Some(trait_ref),
|
||||
self_ty: self_type.clone(),
|
||||
items: ThinVec::new(),
|
||||
})),
|
||||
);
|
||||
push(Annotatable::Item(item));
|
||||
};
|
||||
|
||||
// Create unsized `self`, that is, one where the `#[pointee]` type arg is replaced with `__S`. For
|
||||
// example, instead of `MyType<'a, T>`, it will be `MyType<'a, __S>`.
|
||||
let s_ty = cx.ty_ident(span, Ident::new(sym::__S, span));
|
||||
let mut alt_self_params = self_params;
|
||||
alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone());
|
||||
let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params));
|
||||
|
||||
// Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
|
||||
let mut impl_generics = generics.clone();
|
||||
{
|
||||
let p = &mut impl_generics.params[pointee_param_idx];
|
||||
let arg = GenericArg::Type(s_ty.clone());
|
||||
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
|
||||
p.bounds.push(cx.trait_bound(unsize, false));
|
||||
let mut attrs = thin_vec![];
|
||||
swap(&mut p.attrs, &mut attrs);
|
||||
p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
|
||||
}
|
||||
|
||||
// Add the `__S: ?Sized` extra parameter to the impl block.
|
||||
let sized = cx.path_global(span, path!(span, core::marker::Sized));
|
||||
let bound = GenericBound::Trait(
|
||||
cx.poly_trait_ref(span, sized),
|
||||
TraitBoundModifiers {
|
||||
polarity: ast::BoundPolarity::Maybe(span),
|
||||
constness: ast::BoundConstness::Never,
|
||||
asyncness: ast::BoundAsyncness::Normal,
|
||||
},
|
||||
);
|
||||
let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None);
|
||||
impl_generics.params.push(extra_param);
|
||||
|
||||
// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
|
||||
let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
|
||||
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
|
||||
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone());
|
||||
}
|
||||
|
|
@ -127,6 +127,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
|||
PartialOrd: partial_ord::expand_deriving_partial_ord,
|
||||
RustcDecodable: decodable::expand_deriving_rustc_decodable,
|
||||
RustcEncodable: encodable::expand_deriving_rustc_encodable,
|
||||
SmartPointer: smart_ptr::expand_deriving_smart_ptr,
|
||||
}
|
||||
|
||||
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
||||
|
|
|
|||
|
|
@ -564,9 +564,6 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
|
||||
let llvm_plugins = config.llvm_plugins.join(",");
|
||||
|
||||
// FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
|
||||
// We would have to add upstream support for this first, before we can support
|
||||
// config.inline_threshold and our more aggressive default thresholds.
|
||||
let result = llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
|
|||
|
||||
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
|
||||
|
||||
codegen_ssa_expected_coverage_symbol = expected `coverage(off)` or `coverage(on)`
|
||||
|
||||
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
|
||||
|
||||
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ pub struct ModuleConfig {
|
|||
pub vectorize_loop: bool,
|
||||
pub vectorize_slp: bool,
|
||||
pub merge_functions: bool,
|
||||
pub inline_threshold: Option<u32>,
|
||||
pub emit_lifetime_markers: bool,
|
||||
pub llvm_plugins: Vec<String>,
|
||||
}
|
||||
|
|
@ -280,7 +279,6 @@ impl ModuleConfig {
|
|||
}
|
||||
},
|
||||
|
||||
inline_threshold: sess.opts.cg.inline_threshold,
|
||||
emit_lifetime_markers: sess.emit_lifetime_markers(),
|
||||
llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@ use rustc_span::{sym, Span};
|
|||
use rustc_target::spec::{abi, SanitizerSet};
|
||||
|
||||
use crate::errors;
|
||||
use crate::target_features::from_target_feature;
|
||||
use crate::{
|
||||
errors::{ExpectedCoverageSymbol, ExpectedUsedSymbol},
|
||||
target_features::check_target_feature_trait_unsafe,
|
||||
};
|
||||
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
|
||||
|
||||
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
|
||||
use rustc_middle::mir::mono::Linkage::*;
|
||||
|
|
@ -139,7 +135,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
// coverage on a smaller scope within an excluded larger scope.
|
||||
}
|
||||
Some(_) | None => {
|
||||
tcx.dcx().emit_err(ExpectedCoverageSymbol { span: attr.span });
|
||||
tcx.dcx()
|
||||
.span_delayed_bug(attr.span, "unexpected value of coverage attribute");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -174,7 +171,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.dcx().emit_err(ExpectedUsedSymbol { span: attr.span });
|
||||
tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span });
|
||||
}
|
||||
None => {
|
||||
// Unfortunately, unconditionally using `llvm.used` causes
|
||||
|
|
|
|||
|
|
@ -564,13 +564,6 @@ pub struct UnknownArchiveKind<'a> {
|
|||
pub kind: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_expected_coverage_symbol)]
|
||||
pub struct ExpectedCoverageSymbol {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_expected_used_symbol)]
|
||||
pub struct ExpectedUsedSymbol {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#![feature(lint_reasons)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ impl SipHasher128 {
|
|||
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 {
|
||||
let mut hasher = SipHasher128 {
|
||||
nbuf: 0,
|
||||
buf: MaybeUninit::uninit_array(),
|
||||
buf: [MaybeUninit::uninit(); BUFFER_WITH_SPILL_CAPACITY],
|
||||
state: State {
|
||||
v0: key0 ^ 0x736f6d6570736575,
|
||||
// The XOR with 0xee is only done on 128-bit algorithm version.
|
||||
|
|
|
|||
|
|
@ -238,12 +238,21 @@ pub trait ToStableHashKey<HCX> {
|
|||
/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
|
||||
/// unstable sorting can be used for this type. Set to true if and
|
||||
/// only if `a == b` implies `a` and `b` are fully indistinguishable.
|
||||
pub unsafe trait StableOrd: Ord {
|
||||
pub trait StableOrd: Ord {
|
||||
const CAN_USE_UNSTABLE_SORT: bool;
|
||||
|
||||
/// Marker to ensure that implementors have carefully considered
|
||||
/// whether their `Ord` implementation obeys this trait's contract.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: ();
|
||||
}
|
||||
|
||||
unsafe impl<T: StableOrd> StableOrd for &T {
|
||||
impl<T: StableOrd> StableOrd for &T {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
|
||||
|
||||
// Ordering of a reference is exactly that of the referent, and since
|
||||
// the ordering of the referet is stable so must be the ordering of the
|
||||
// reference.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
|
||||
|
|
@ -290,8 +299,12 @@ macro_rules! impl_stable_traits_for_trivial_type {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::stable_hasher::StableOrd for $t {
|
||||
impl $crate::stable_hasher::StableOrd for $t {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// Encoding and decoding doesn't change the bytes of trivial types
|
||||
// and `Ord::cmp` depends only on those bytes.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -327,8 +340,12 @@ impl<CTX> HashStable<CTX> for Hash128 {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl StableOrd for Hash128 {
|
||||
impl StableOrd for Hash128 {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// Encoding and decoding doesn't change the bytes of `Hash128`
|
||||
// and `Ord::cmp` depends only on those bytes.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for ! {
|
||||
|
|
@ -392,8 +409,12 @@ impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2)
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
|
||||
impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT;
|
||||
|
||||
// Ordering of tuples is a pure function of their elements' ordering, and since
|
||||
// the ordering of each element is stable so must be the ordering of the tuple.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
|
||||
|
|
@ -410,9 +431,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
|
||||
impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
|
||||
const CAN_USE_UNSTABLE_SORT: bool =
|
||||
T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
|
||||
|
||||
// Ordering of tuples is a pure function of their elements' ordering, and since
|
||||
// the ordering of each element is stable so must be the ordering of the tuple.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
|
||||
|
|
@ -431,13 +456,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd
|
||||
for (T1, T2, T3, T4)
|
||||
{
|
||||
impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
|
||||
&& T2::CAN_USE_UNSTABLE_SORT
|
||||
&& T3::CAN_USE_UNSTABLE_SORT
|
||||
&& T4::CAN_USE_UNSTABLE_SORT;
|
||||
|
||||
// Ordering of tuples is a pure function of their elements' ordering, and since
|
||||
// the ordering of each element is stable so must be the ordering of the tuple.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
|
||||
|
|
@ -530,8 +557,12 @@ impl<CTX> HashStable<CTX> for str {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl StableOrd for &str {
|
||||
impl StableOrd for &str {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// Encoding and decoding doesn't change the bytes of string slices
|
||||
// and `Ord::cmp` depends only on those bytes.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for String {
|
||||
|
|
@ -541,10 +572,12 @@ impl<CTX> HashStable<CTX> for String {
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: String comparison only depends on their contents and the
|
||||
// contents are not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for String {
|
||||
impl StableOrd for String {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// String comparison only depends on their contents and the
|
||||
// contents are not changed by (de-)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<HCX> ToStableHashKey<HCX> for String {
|
||||
|
|
@ -570,9 +603,11 @@ impl<CTX> HashStable<CTX> for bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: sort order of bools is not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for bool {
|
||||
impl StableOrd for bool {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// sort order of bools is not changed by (de-)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<T, CTX> HashStable<CTX> for Option<T>
|
||||
|
|
@ -590,9 +625,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// Safety: the Option wrapper does not add instability to comparison.
|
||||
unsafe impl<T: StableOrd> StableOrd for Option<T> {
|
||||
impl<T: StableOrd> StableOrd for Option<T> {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
|
||||
|
||||
// the Option wrapper does not add instability to comparison.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
|||
};
|
||||
use rustc_feature::find_gated_cfg;
|
||||
use rustc_interface::util::{self, get_codegen_backend};
|
||||
use rustc_interface::{interface, Queries};
|
||||
use rustc_interface::{interface, passes, Queries};
|
||||
use rustc_lint::unerased_lint_store;
|
||||
use rustc_metadata::creader::MetadataLoader;
|
||||
use rustc_metadata::locator;
|
||||
|
|
@ -367,18 +367,17 @@ fn run_compiler(
|
|||
return early_exit();
|
||||
}
|
||||
|
||||
let early_dcx = EarlyDiagCtxt::new(sess.opts.error_format);
|
||||
|
||||
if print_crate_info(&early_dcx, codegen_backend, sess, has_input) == Compilation::Stop {
|
||||
if print_crate_info(codegen_backend, sess, has_input) == Compilation::Stop {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if !has_input {
|
||||
early_dcx.early_fatal("no input filename given"); // this is fatal
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("no input filename given"); // this is fatal
|
||||
}
|
||||
|
||||
if !sess.opts.unstable_opts.ls.is_empty() {
|
||||
list_metadata(&early_dcx, sess, &*codegen_backend.metadata_loader());
|
||||
list_metadata(sess, &*codegen_backend.metadata_loader());
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +398,9 @@ fn run_compiler(
|
|||
Ok(())
|
||||
})?;
|
||||
|
||||
queries.write_dep_info()?;
|
||||
queries.global_ctxt()?.enter(|tcx| {
|
||||
passes::write_dep_info(tcx);
|
||||
});
|
||||
} else {
|
||||
let krate = queries.parse()?;
|
||||
pretty::print(
|
||||
|
|
@ -427,7 +428,9 @@ fn run_compiler(
|
|||
return early_exit();
|
||||
}
|
||||
|
||||
queries.write_dep_info()?;
|
||||
queries.global_ctxt()?.enter(|tcx| {
|
||||
passes::write_dep_info(tcx);
|
||||
});
|
||||
|
||||
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
||||
&& sess.opts.output_types.len() == 1
|
||||
|
|
@ -670,7 +673,7 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
|
|||
}
|
||||
}
|
||||
|
||||
fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dyn MetadataLoader) {
|
||||
fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
|
||||
match sess.io.input {
|
||||
Input::File(ref ifile) => {
|
||||
let path = &(*ifile);
|
||||
|
|
@ -687,13 +690,13 @@ fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dy
|
|||
safe_println!("{}", String::from_utf8(v).unwrap());
|
||||
}
|
||||
Input::Str { .. } => {
|
||||
early_dcx.early_fatal("cannot list metadata for stdin");
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("cannot list metadata for stdin");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_crate_info(
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
codegen_backend: &dyn CodegenBackend,
|
||||
sess: &Session,
|
||||
parse_attrs: bool,
|
||||
|
|
@ -877,8 +880,8 @@ fn print_crate_info(
|
|||
.expect("unknown Apple target OS");
|
||||
println_info!("deployment_target={}", format!("{major}.{minor}"))
|
||||
} else {
|
||||
early_dcx
|
||||
.early_fatal("only Apple targets currently support deployment version info")
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("only Apple targets currently support deployment version info")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1133,7 +1136,11 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
|
|||
}
|
||||
|
||||
if cg_flags.iter().any(|x| *x == "no-stack-check") {
|
||||
early_dcx.early_warn("the --no-stack-check flag is deprecated and does nothing");
|
||||
early_dcx.early_warn("the `-Cno-stack-check` flag is deprecated and does nothing");
|
||||
}
|
||||
|
||||
if cg_flags.iter().any(|x| x.starts_with("inline-threshold")) {
|
||||
early_dcx.early_warn("the `-Cinline-threshold` flag is deprecated and does nothing (consider using `-Cllvm-args=--inline-threshold=...`)");
|
||||
}
|
||||
|
||||
if cg_flags.iter().any(|x| *x == "passes=list") {
|
||||
|
|
|
|||
|
|
@ -902,7 +902,7 @@ impl HumanEmitter {
|
|||
// <EMPTY LINE>
|
||||
//
|
||||
let mut annotations_position = vec![];
|
||||
let mut line_len = 0;
|
||||
let mut line_len: usize = 0;
|
||||
let mut p = 0;
|
||||
for (i, annotation) in annotations.iter().enumerate() {
|
||||
for (j, next) in annotations.iter().enumerate() {
|
||||
|
|
@ -973,6 +973,31 @@ impl HumanEmitter {
|
|||
return vec![];
|
||||
}
|
||||
|
||||
if annotations_position
|
||||
.iter()
|
||||
.all(|(_, ann)| matches!(ann.annotation_type, AnnotationType::MultilineStart(_)))
|
||||
&& let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max()
|
||||
{
|
||||
// Special case the following, so that we minimize overlapping multiline spans.
|
||||
//
|
||||
// 3 │ X0 Y0 Z0
|
||||
// │ ┏━━━━━┛ │ │ < We are writing these lines
|
||||
// │ ┃┌───────┘ │ < by reverting the "depth" of
|
||||
// │ ┃│┌─────────┘ < their multilne spans.
|
||||
// 4 │ ┃││ X1 Y1 Z1
|
||||
// 5 │ ┃││ X2 Y2 Z2
|
||||
// │ ┃│└────╿──│──┘ `Z` label
|
||||
// │ ┃└─────│──┤
|
||||
// │ ┗━━━━━━┥ `Y` is a good letter too
|
||||
// ╰╴ `X` is a good letter
|
||||
for (pos, _) in &mut annotations_position {
|
||||
*pos = max_pos - *pos;
|
||||
}
|
||||
// We know then that we don't need an additional line for the span label, saving us
|
||||
// one line of vertical space.
|
||||
line_len = line_len.saturating_sub(1);
|
||||
}
|
||||
|
||||
// Write the column separator.
|
||||
//
|
||||
// After this we will have:
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ pub struct AttributeTemplate {
|
|||
pub word: bool,
|
||||
/// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`.
|
||||
pub list: Option<&'static str>,
|
||||
/// If non-empty, the attribute is allowed to take a list containing exactly
|
||||
/// one of the listed words, like `#[coverage(off)]`.
|
||||
pub one_of: &'static [Symbol],
|
||||
/// If `Some`, the attribute is allowed to be a name/value pair where the
|
||||
/// value is a string, like `#[must_use = "reason"]`.
|
||||
pub name_value_str: Option<&'static str>,
|
||||
|
|
@ -165,19 +168,20 @@ pub enum AttributeDuplicates {
|
|||
/// E.g., `template!(Word, List: "description")` means that the attribute
|
||||
/// supports forms `#[attr]` and `#[attr(description)]`.
|
||||
macro_rules! template {
|
||||
(Word) => { template!(@ true, None, None) };
|
||||
(List: $descr: expr) => { template!(@ false, Some($descr), None) };
|
||||
(NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) };
|
||||
(Word, List: $descr: expr) => { template!(@ true, Some($descr), None) };
|
||||
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) };
|
||||
(Word) => { template!(@ true, None, &[], None) };
|
||||
(List: $descr: expr) => { template!(@ false, Some($descr), &[], None) };
|
||||
(OneOf: $one_of: expr) => { template!(@ false, None, $one_of, None) };
|
||||
(NameValueStr: $descr: expr) => { template!(@ false, None, &[], Some($descr)) };
|
||||
(Word, List: $descr: expr) => { template!(@ true, Some($descr), &[], None) };
|
||||
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, &[], Some($descr)) };
|
||||
(List: $descr1: expr, NameValueStr: $descr2: expr) => {
|
||||
template!(@ false, Some($descr1), Some($descr2))
|
||||
template!(@ false, Some($descr1), &[], Some($descr2))
|
||||
};
|
||||
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
|
||||
template!(@ true, Some($descr1), Some($descr2))
|
||||
template!(@ true, Some($descr1), &[], Some($descr2))
|
||||
};
|
||||
(@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
|
||||
word: $word, list: $list, name_value_str: $name_value_str
|
||||
(@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { AttributeTemplate {
|
||||
word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str
|
||||
} };
|
||||
}
|
||||
|
||||
|
|
@ -478,8 +482,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::No, experimental!(no_sanitize)
|
||||
),
|
||||
gated!(
|
||||
coverage, Normal, template!(Word, List: "on|off"),
|
||||
WarnFollowing, EncodeCrossCrate::No,
|
||||
coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
|
||||
ErrorPreceding, EncodeCrossCrate::No,
|
||||
coverage_attribute, experimental!(coverage)
|
||||
),
|
||||
|
||||
|
|
@ -575,6 +579,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::No, coroutines, experimental!(coroutines)
|
||||
),
|
||||
|
||||
// `#[pointee]` attribute to designate the pointee type in SmartPointer derive-macro
|
||||
gated!(
|
||||
pointee, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes: Stability, deprecation, and unsafe:
|
||||
// ==========================================================================
|
||||
|
|
|
|||
|
|
@ -436,6 +436,8 @@ declare_features! (
|
|||
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
|
||||
/// Allows deref patterns.
|
||||
(incomplete, deref_patterns, "1.79.0", Some(87121)),
|
||||
/// Allows deriving `SmartPointer` traits
|
||||
(unstable, derive_smart_pointer, "1.79.0", Some(123430)),
|
||||
/// Controls errors in trait implementations.
|
||||
(unstable, do_not_recommend, "1.67.0", Some(51992)),
|
||||
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
|
||||
|
|
|
|||
|
|
@ -165,10 +165,12 @@ impl ItemLocalId {
|
|||
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
|
||||
}
|
||||
|
||||
// Safety: Ord is implement as just comparing the ItemLocalId's numerical
|
||||
// values and these are not changed by (de-)serialization.
|
||||
unsafe impl StableOrd for ItemLocalId {
|
||||
impl StableOrd for ItemLocalId {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// `Ord` is implemented as just comparing the ItemLocalId's numerical
|
||||
// values and these are not changed by (de-)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
tcx,
|
||||
assoc_item,
|
||||
assoc_item,
|
||||
ty::TraitRef::new(tcx, def_id.to_def_id(), trait_args),
|
||||
ty::TraitRef::new_from_args(tcx, def_id.to_def_id(), trait_args),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -2032,7 +2032,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
// to its definition type. This should be the param-env we use to *prove* the
|
||||
// predicate too, but we don't do that because of performance issues.
|
||||
// See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
|
||||
let trait_projection_ty = Ty::new_projection(tcx, trait_ty.def_id, rebased_args);
|
||||
let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
|
||||
let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
|
||||
let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
|
||||
for mut obligation in util::elaborate(tcx, obligations) {
|
||||
|
|
@ -2230,7 +2230,11 @@ fn param_env_with_gat_bounds<'tcx>(
|
|||
_ => predicates.push(
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::ProjectionPredicate {
|
||||
projection_term: ty::AliasTerm::new(tcx, trait_ty.def_id, rebased_args),
|
||||
projection_term: ty::AliasTerm::new_from_args(
|
||||
tcx,
|
||||
trait_ty.def_id,
|
||||
rebased_args,
|
||||
),
|
||||
term: normalize_impl_ty.into(),
|
||||
},
|
||||
bound_vars,
|
||||
|
|
|
|||
|
|
@ -504,7 +504,11 @@ pub fn check_intrinsic_type(
|
|||
ty::Region::new_bound(tcx, ty::INNERMOST, br),
|
||||
param(0),
|
||||
)],
|
||||
Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])),
|
||||
Ty::new_projection_from_args(
|
||||
tcx,
|
||||
discriminant_def_id,
|
||||
tcx.mk_args(&[param(0).into()]),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
|||
item_segment,
|
||||
trait_ref.args,
|
||||
);
|
||||
Ty::new_projection(self.tcx(), item_def_id, item_args)
|
||||
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
|
||||
} else {
|
||||
// There are no late-bound regions; we can just ignore the binder.
|
||||
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
|
||||
|
|
@ -1607,7 +1607,7 @@ pub fn suggest_impl_trait<'tcx>(
|
|||
let item_ty = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
Ty::new_projection(infcx.tcx, assoc_item_def_id, args),
|
||||
Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
|
||||
);
|
||||
// FIXME(compiler-errors): We may benefit from resolving regions here.
|
||||
if ocx.select_where_possible().is_empty()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ fn associated_type_bounds<'tcx>(
|
|||
span: Span,
|
||||
filter: PredicateFilter,
|
||||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
let item_ty = Ty::new_projection(
|
||||
let item_ty = Ty::new_projection_from_args(
|
||||
tcx,
|
||||
assoc_item_def_id.to_def_id(),
|
||||
GenericArgs::identity_for_item(tcx, assoc_item_def_id),
|
||||
|
|
@ -108,7 +108,7 @@ pub(super) fn explicit_item_bounds_with_filter(
|
|||
tcx,
|
||||
opaque_def_id.expect_local(),
|
||||
opaque_ty.bounds,
|
||||
Ty::new_projection(
|
||||
Ty::new_projection_from_args(
|
||||
tcx,
|
||||
def_id.to_def_id(),
|
||||
ty::GenericArgs::identity_for_item(tcx, def_id),
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
);
|
||||
debug!(?alias_args);
|
||||
|
||||
ty::AliasTerm::new(tcx, assoc_item.def_id, alias_args)
|
||||
ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
|
||||
});
|
||||
|
||||
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
|
||||
|
|
|
|||
|
|
@ -693,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
debug!(?bound_vars);
|
||||
|
||||
let poly_trait_ref = ty::Binder::bind_with_vars(
|
||||
ty::TraitRef::new(tcx, trait_def_id, generic_args),
|
||||
ty::TraitRef::new_from_args(tcx, trait_def_id, generic_args),
|
||||
bound_vars,
|
||||
);
|
||||
|
||||
|
|
@ -759,7 +759,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
Some((trait_def_id, trait_segment, span)),
|
||||
);
|
||||
}
|
||||
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
|
||||
ty::TraitRef::new_from_args(self.tcx(), trait_def_id, generic_args)
|
||||
}
|
||||
|
||||
fn probe_trait_that_defines_assoc_item(
|
||||
|
|
@ -789,7 +789,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Type aliases defined in crates that have the
|
||||
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
|
||||
// then actually instantiate the where bounds of.
|
||||
let alias_ty = ty::AliasTy::new(tcx, did, args);
|
||||
let alias_ty = ty::AliasTy::new_from_args(tcx, did, args);
|
||||
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||
} else {
|
||||
tcx.at(span).type_of(did).instantiate(tcx, args)
|
||||
|
|
@ -1267,7 +1267,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.chain(args.into_iter().skip(parent_args.len())),
|
||||
);
|
||||
|
||||
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
|
||||
let ty =
|
||||
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
|
||||
|
||||
Ok(Some((ty, assoc_item)))
|
||||
}
|
||||
|
|
@ -1534,7 +1535,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let item_args =
|
||||
self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
|
||||
|
||||
Ty::new_projection(tcx, item_def_id, item_args)
|
||||
Ty::new_projection_from_args(tcx, item_def_id, item_args)
|
||||
}
|
||||
|
||||
pub fn prohibit_generic_args<'a>(
|
||||
|
|
@ -2302,7 +2303,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
debug!(?args);
|
||||
|
||||
if in_trait {
|
||||
Ty::new_projection(tcx, def_id, args)
|
||||
Ty::new_projection_from_args(tcx, def_id, args)
|
||||
} else {
|
||||
Ty::new_opaque(tcx, def_id, args)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1245,11 +1245,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
expr,
|
||||
);
|
||||
|
||||
return self
|
||||
return Err(self
|
||||
.commit_if_ok(|_| {
|
||||
self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty)
|
||||
self.at(cause, self.param_env).lub(DefineOpaqueTypes::Yes, prev_ty, new_ty)
|
||||
})
|
||||
.map(|ok| self.register_infer_ok_obligations(ok));
|
||||
.unwrap_err());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1259,10 +1259,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(e) = first_error {
|
||||
Err(e)
|
||||
} else {
|
||||
self.commit_if_ok(|_| {
|
||||
self.at(cause, self.param_env).lub(DefineOpaqueTypes::No, prev_ty, new_ty)
|
||||
})
|
||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||
Err(self
|
||||
.commit_if_ok(|_| {
|
||||
self.at(cause, self.param_env).lub(
|
||||
DefineOpaqueTypes::Yes,
|
||||
prev_ty,
|
||||
new_ty,
|
||||
)
|
||||
})
|
||||
.unwrap_err())
|
||||
}
|
||||
}
|
||||
Ok(ok) => {
|
||||
|
|
|
|||
|
|
@ -3108,7 +3108,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let element_ty = ocx.normalize(
|
||||
&cause,
|
||||
self.param_env,
|
||||
Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
|
||||
Ty::new_projection_from_args(
|
||||
self.tcx,
|
||||
index_trait_output_def_id,
|
||||
impl_trait_ref.args,
|
||||
),
|
||||
);
|
||||
|
||||
let true_errors = ocx.select_where_possible();
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
|
||||
// that struct type.
|
||||
let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
|
||||
ty::TraitRef::new(
|
||||
ty::TraitRef::new_from_args(
|
||||
self.tcx,
|
||||
obligation.impl_or_alias_def_id,
|
||||
ty::GenericArgs::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
|
|||
trait_ref.args,
|
||||
);
|
||||
|
||||
Ty::new_projection(self.tcx(), item_def_id, item_args)
|
||||
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
|
||||
}
|
||||
|
||||
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Special-case transmuting from `typeof(function)` and
|
||||
// `Option<typeof(function)>` to present a clearer error.
|
||||
let from = unpack_option_like(tcx, from);
|
||||
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to)
|
||||
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to, _)) = (from.kind(), sk_to)
|
||||
&& size_to == Pointer(dl.instruction_address_space).size(&tcx)
|
||||
{
|
||||
struct_span_code_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type")
|
||||
|
|
@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Try to display a sensible error with as much information as possible.
|
||||
let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
|
||||
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
|
||||
Ok(SizeSkeleton::Known(size)) => {
|
||||
Ok(SizeSkeleton::Known(size, _)) => {
|
||||
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
|
||||
format!("{v} bits")
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.var_for_def(cause.span, param)
|
||||
});
|
||||
|
||||
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, args);
|
||||
let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, args);
|
||||
|
||||
// Construct an obligation
|
||||
let poly_trait_ref = ty::Binder::dummy(trait_ref);
|
||||
|
|
|
|||
|
|
@ -870,7 +870,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
trait_def_id: DefId,
|
||||
) {
|
||||
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
|
||||
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
|
||||
let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args);
|
||||
|
||||
if self.tcx.is_trait_alias(trait_def_id) {
|
||||
// For trait aliases, recursively assume all explicitly named traits are relevant
|
||||
|
|
|
|||
|
|
@ -1978,7 +1978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err,
|
||||
self_source,
|
||||
args,
|
||||
ty::TraitRef::new(
|
||||
ty::TraitRef::new_from_args(
|
||||
self.tcx,
|
||||
trait_did,
|
||||
self.fresh_args_for_item(sugg_span, trait_did),
|
||||
|
|
|
|||
|
|
@ -256,12 +256,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
|||
(false, None, None, Some(span), String::new())
|
||||
};
|
||||
|
||||
let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
|
||||
let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
|
||||
self.cx.tcx,
|
||||
trait_def_id,
|
||||
expected_args,
|
||||
));
|
||||
let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
|
||||
let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new_from_args(
|
||||
self.cx.tcx,
|
||||
trait_def_id,
|
||||
actual_args,
|
||||
|
|
|
|||
|
|
@ -495,9 +495,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
let res = {
|
||||
// If `f` panics, `finish_diagnostics` will run during
|
||||
// unwinding because of the `defer`.
|
||||
let mut guar = None;
|
||||
let sess_abort_guard = defer(|| {
|
||||
guar = compiler.sess.finish_diagnostics(&config.registry);
|
||||
compiler.sess.finish_diagnostics(&config.registry);
|
||||
});
|
||||
|
||||
let res = f(&compiler);
|
||||
|
|
@ -506,16 +505,14 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
// normally when `sess_abort_guard` is dropped.
|
||||
drop(sess_abort_guard);
|
||||
|
||||
// If `finish_diagnostics` emits errors (e.g. stashed
|
||||
// errors) we can't return an error directly, because the
|
||||
// return type of this function is `R`, not `Result<R, E>`.
|
||||
// But we need to communicate the errors' existence to the
|
||||
// caller, otherwise the caller might mistakenly think that
|
||||
// no errors occurred and return a zero exit code. So we
|
||||
// abort (panic) instead, similar to if `f` had panicked.
|
||||
if guar.is_some() {
|
||||
compiler.sess.dcx().abort_if_errors();
|
||||
}
|
||||
// If error diagnostics have been emitted, we can't return an
|
||||
// error directly, because the return type of this function
|
||||
// is `R`, not `Result<R, E>`. But we need to communicate the
|
||||
// errors' existence to the caller, otherwise the caller might
|
||||
// mistakenly think that no errors occurred and return a zero
|
||||
// exit code. So we abort (panic) instead, similar to if `f`
|
||||
// had panicked.
|
||||
compiler.sess.dcx().abort_if_errors();
|
||||
|
||||
res
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
mod callbacks;
|
||||
mod errors;
|
||||
pub mod interface;
|
||||
mod passes;
|
||||
pub mod passes;
|
||||
mod proc_macro_decls;
|
||||
mod queries;
|
||||
pub mod util;
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ use rustc_ast::{self as ast, visit};
|
|||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{Lrc, OnceLock, WorkerLocal};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
|
||||
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
|
||||
use rustc_feature::Features;
|
||||
use rustc_fs_util::try_canonicalize;
|
||||
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_incremental::setup_dep_graph;
|
||||
use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::DepGraph;
|
||||
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_parse::{
|
||||
|
|
@ -28,6 +28,7 @@ use rustc_session::code_stats::VTableSizeInfo;
|
|||
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
|
||||
use rustc_session::cstore::Untracked;
|
||||
use rustc_session::output::filename_for_input;
|
||||
use rustc_session::output::{collect_crate_types, find_crate_name};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::{Limit, Session};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
|
@ -39,20 +40,22 @@ use std::any::Any;
|
|||
use std::ffi::OsString;
|
||||
use std::io::{self, BufWriter, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use std::{env, fs, iter};
|
||||
use tracing::{info, instrument};
|
||||
|
||||
pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
|
||||
let krate = sess.time("parse_crate", || {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
Input::Str { input, name } => {
|
||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
||||
}
|
||||
});
|
||||
parser.parse_crate_mod()
|
||||
})?;
|
||||
pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
|
||||
let krate = sess
|
||||
.time("parse_crate", || {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
Input::Str { input, name } => {
|
||||
new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
|
||||
}
|
||||
});
|
||||
parser.parse_crate_mod()
|
||||
})
|
||||
.map_err(|parse_error| parse_error.emit())?;
|
||||
|
||||
if sess.opts.unstable_opts.input_stats {
|
||||
eprintln!("Lines of code: {}", sess.source_map().count_lines());
|
||||
|
|
@ -559,7 +562,7 @@ fn resolver_for_lowering_raw<'tcx>(
|
|||
(tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
|
||||
}
|
||||
|
||||
pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) {
|
||||
pub fn write_dep_info(tcx: TyCtxt<'_>) {
|
||||
// Make sure name resolution and macro expansion is run for
|
||||
// the side-effect of providing a complete set of all
|
||||
// accessed files and env vars.
|
||||
|
|
@ -640,22 +643,48 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
|
|||
*providers
|
||||
});
|
||||
|
||||
pub fn create_global_ctxt<'tcx>(
|
||||
pub(crate) fn create_global_ctxt<'tcx>(
|
||||
compiler: &'tcx Compiler,
|
||||
crate_types: Vec<CrateType>,
|
||||
stable_crate_id: StableCrateId,
|
||||
dep_graph: DepGraph,
|
||||
untracked: Untracked,
|
||||
mut krate: rustc_ast::Crate,
|
||||
gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
|
||||
) -> &'tcx GlobalCtxt<'tcx> {
|
||||
) -> Result<&'tcx GlobalCtxt<'tcx>> {
|
||||
let sess = &compiler.sess;
|
||||
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
&mut krate,
|
||||
&sess.psess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
);
|
||||
|
||||
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||
|
||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
||||
let crate_name = find_crate_name(sess, &pre_configured_attrs);
|
||||
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
|
||||
let stable_crate_id = StableCrateId::new(
|
||||
crate_name,
|
||||
crate_types.contains(&CrateType::Executable),
|
||||
sess.opts.cg.metadata.clone(),
|
||||
sess.cfg_version,
|
||||
);
|
||||
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
|
||||
let dep_graph = setup_dep_graph(sess)?;
|
||||
|
||||
let cstore =
|
||||
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
|
||||
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
|
||||
|
||||
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
|
||||
let untracked =
|
||||
Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids };
|
||||
|
||||
// We're constructing the HIR here; we don't care what we will
|
||||
// read, since we haven't even constructed the *input* to
|
||||
// incr. comp. yet.
|
||||
dep_graph.assert_ignored();
|
||||
|
||||
let sess = &compiler.sess;
|
||||
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
|
||||
|
||||
let codegen_backend = &compiler.codegen_backend;
|
||||
|
|
@ -669,7 +698,7 @@ pub fn create_global_ctxt<'tcx>(
|
|||
let incremental = dep_graph.is_fully_enabled();
|
||||
|
||||
sess.time("setup_global_ctxt", || {
|
||||
gcx_cell.get_or_init(move || {
|
||||
let qcx = gcx_cell.get_or_init(move || {
|
||||
TyCtxt::create_global_ctxt(
|
||||
sess,
|
||||
crate_types,
|
||||
|
|
@ -688,7 +717,23 @@ pub fn create_global_ctxt<'tcx>(
|
|||
providers.hooks,
|
||||
compiler.current_gcx.clone(),
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
qcx.enter(|tcx| {
|
||||
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
|
||||
assert_eq!(feed.key(), LOCAL_CRATE);
|
||||
feed.crate_name(crate_name);
|
||||
|
||||
let feed = tcx.feed_unit_query();
|
||||
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
|
||||
sess,
|
||||
&pre_configured_attrs,
|
||||
crate_name,
|
||||
)));
|
||||
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
|
||||
feed.output_filenames(Arc::new(outputs));
|
||||
});
|
||||
Ok(qcx)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -924,12 +969,56 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
|
||||
/// to write UI tests that actually test that compilation succeeds without reporting
|
||||
/// an error.
|
||||
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
|
||||
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
|
||||
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
|
||||
match attr.meta_item_list() {
|
||||
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
|
||||
Some(list)
|
||||
if list.iter().any(|list_item| {
|
||||
matches!(
|
||||
list_item.ident().map(|i| i.name),
|
||||
Some(sym::delayed_bug_from_inside_query)
|
||||
)
|
||||
}) =>
|
||||
{
|
||||
tcx.ensure().trigger_delayed_bug(def_id);
|
||||
}
|
||||
|
||||
// Bare `#[rustc_error]`.
|
||||
None => {
|
||||
tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) });
|
||||
}
|
||||
|
||||
// Some other attribute.
|
||||
Some(_) => {
|
||||
tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation {
|
||||
span: tcx.def_span(def_id),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the codegen backend, after which the AST and analysis can
|
||||
/// be discarded.
|
||||
pub fn start_codegen<'tcx>(
|
||||
pub(crate) fn start_codegen<'tcx>(
|
||||
codegen_backend: &dyn CodegenBackend,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Box<dyn Any> {
|
||||
) -> Result<Box<dyn Any>> {
|
||||
// Don't do code generation if there were any errors. Likewise if
|
||||
// there were any delayed bugs, because codegen will likely cause
|
||||
// more ICEs, obscuring the original problem.
|
||||
if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
// Hook for UI tests.
|
||||
check_for_rustc_errors_attr(tcx);
|
||||
|
||||
info!("Pre-codegen\n{:?}", tcx.debug_stats());
|
||||
|
||||
let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
|
||||
|
|
@ -952,7 +1041,7 @@ pub fn start_codegen<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
codegen
|
||||
Ok(codegen)
|
||||
}
|
||||
|
||||
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,20 @@
|
|||
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
|
||||
use crate::errors::FailedWritingFile;
|
||||
use crate::interface::{Compiler, Result};
|
||||
use crate::{errors, passes, util};
|
||||
use crate::{errors, passes};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_codegen_ssa::CodegenResults;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
|
||||
use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_incremental::setup_dep_graph;
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_data_structures::sync::{OnceLock, WorkerLocal};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::DepGraph;
|
||||
use rustc_middle::ty::{GlobalCtxt, TyCtxt};
|
||||
use rustc_serialize::opaque::FileEncodeResult;
|
||||
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
|
||||
use rustc_session::cstore::Untracked;
|
||||
use rustc_session::output::{collect_crate_types, find_crate_name};
|
||||
use rustc_session::config::{self, OutputFilenames, OutputType};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use std::any::Any;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::sync::Arc;
|
||||
|
|
@ -106,133 +100,26 @@ impl<'tcx> Queries<'tcx> {
|
|||
}
|
||||
|
||||
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
|
||||
self.parse.compute(|| {
|
||||
passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit())
|
||||
})
|
||||
self.parse.compute(|| passes::parse(&self.compiler.sess))
|
||||
}
|
||||
|
||||
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
||||
self.gcx.compute(|| {
|
||||
let sess = &self.compiler.sess;
|
||||
let krate = self.parse()?.steal();
|
||||
|
||||
let mut krate = self.parse()?.steal();
|
||||
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
&mut krate,
|
||||
&sess.psess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
);
|
||||
|
||||
let pre_configured_attrs =
|
||||
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||
|
||||
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
|
||||
let crate_name = find_crate_name(sess, &pre_configured_attrs);
|
||||
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
|
||||
let stable_crate_id = StableCrateId::new(
|
||||
crate_name,
|
||||
crate_types.contains(&CrateType::Executable),
|
||||
sess.opts.cg.metadata.clone(),
|
||||
sess.cfg_version,
|
||||
);
|
||||
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
|
||||
let dep_graph = setup_dep_graph(sess)?;
|
||||
|
||||
let cstore = FreezeLock::new(Box::new(CStore::new(
|
||||
self.compiler.codegen_backend.metadata_loader(),
|
||||
)) as _);
|
||||
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
|
||||
|
||||
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
|
||||
let untracked = Untracked {
|
||||
cstore,
|
||||
source_span: AppendOnlyIndexVec::new(),
|
||||
definitions,
|
||||
stable_crate_ids,
|
||||
};
|
||||
|
||||
let qcx = passes::create_global_ctxt(
|
||||
passes::create_global_ctxt(
|
||||
self.compiler,
|
||||
crate_types,
|
||||
stable_crate_id,
|
||||
dep_graph,
|
||||
untracked,
|
||||
krate,
|
||||
&self.gcx_cell,
|
||||
&self.arena,
|
||||
&self.hir_arena,
|
||||
);
|
||||
|
||||
qcx.enter(|tcx| {
|
||||
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
|
||||
assert_eq!(feed.key(), LOCAL_CRATE);
|
||||
feed.crate_name(crate_name);
|
||||
|
||||
let feed = tcx.feed_unit_query();
|
||||
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
|
||||
sess,
|
||||
&pre_configured_attrs,
|
||||
crate_name,
|
||||
)));
|
||||
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
|
||||
feed.output_filenames(Arc::new(outputs));
|
||||
});
|
||||
Ok(qcx)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_dep_info(&'tcx self) -> Result<()> {
|
||||
self.global_ctxt()?.enter(|tcx| {
|
||||
passes::write_dep_info(tcx);
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
|
||||
/// to write UI tests that actually test that compilation succeeds without reporting
|
||||
/// an error.
|
||||
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
|
||||
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
|
||||
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
|
||||
match attr.meta_item_list() {
|
||||
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
|
||||
Some(list)
|
||||
if list.iter().any(|list_item| {
|
||||
matches!(
|
||||
list_item.ident().map(|i| i.name),
|
||||
Some(sym::delayed_bug_from_inside_query)
|
||||
)
|
||||
}) =>
|
||||
{
|
||||
tcx.ensure().trigger_delayed_bug(def_id);
|
||||
}
|
||||
|
||||
// Bare `#[rustc_error]`.
|
||||
None => {
|
||||
tcx.dcx().emit_fatal(RustcErrorFatal { span: tcx.def_span(def_id) });
|
||||
}
|
||||
|
||||
// Some other attribute.
|
||||
Some(_) => {
|
||||
tcx.dcx()
|
||||
.emit_warn(RustcErrorUnexpectedAnnotation { span: tcx.def_span(def_id) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> {
|
||||
self.global_ctxt()?.enter(|tcx| {
|
||||
// Don't do code generation if there were any errors. Likewise if
|
||||
// there were any delayed bugs, because codegen will likely cause
|
||||
// more ICEs, obscuring the original problem.
|
||||
if let Some(guar) = self.compiler.sess.dcx().has_errors_or_delayed_bugs() {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
// Hook for UI tests.
|
||||
Self::check_for_rustc_errors_attr(tcx);
|
||||
|
||||
let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx);
|
||||
let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx)?;
|
||||
|
||||
Ok(Linker {
|
||||
dep_graph: tcx.dep_graph.clone(),
|
||||
|
|
|
|||
|
|
@ -604,6 +604,9 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound
|
|||
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
|
||||
.suggestion = use pat_param to preserve semantics
|
||||
|
||||
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope
|
||||
.help = import `macro_rules` with `use` to make it callable above its definition
|
||||
|
||||
lint_overflowing_bin_hex = literal out of range for `{$ty}`
|
||||
.negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
|
||||
.negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
|
||||
|
|
|
|||
|
|
@ -434,5 +434,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
|
|||
lints::InnerAttributeUnstable::CustomInnerAttribute
|
||||
}
|
||||
.decorate_lint(diag),
|
||||
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
|
||||
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2911,3 +2911,10 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
|
|||
#[suggestion_part(code = ")")]
|
||||
pub right: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_out_of_scope_macro_calls)]
|
||||
#[help]
|
||||
pub struct OutOfScopeMacroCalls {
|
||||
pub path: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
return;
|
||||
}
|
||||
|
||||
let proj_ty = Ty::new_projection(
|
||||
let proj_ty = Ty::new_projection_from_args(
|
||||
cx.tcx,
|
||||
proj.projection_term.def_id,
|
||||
proj.projection_term.args,
|
||||
|
|
|
|||
|
|
@ -4945,3 +4945,42 @@ declare_lint! {
|
|||
reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `out_of_scope_macro_calls` lint detects `macro_rules` called when they are not in scope,
|
||||
/// above their definition, which may happen in key-value attributes.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #![doc = in_root!()]
|
||||
///
|
||||
/// macro_rules! in_root { () => { "" } }
|
||||
///
|
||||
/// fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The scope in which a `macro_rules` item is visible starts at that item and continues
|
||||
/// below it. This is more similar to `let` than to other items, which are in scope both above
|
||||
/// and below their definition.
|
||||
/// Due to a bug `macro_rules` were accidentally in scope inside some key-value attributes
|
||||
/// above their definition. The lint catches such cases.
|
||||
/// To address the issue turn the `macro_rules` into a regularly scoped item by importing it
|
||||
/// with `use`.
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this to a
|
||||
/// hard error in the future.
|
||||
///
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub OUT_OF_SCOPE_MACRO_CALLS,
|
||||
Warn,
|
||||
"detects out of scope calls to `macro_rules` in key-value attributes",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
|
||||
reference: "issue #124535 <https://github.com/rust-lang/rust/issues/124535>",
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -744,6 +744,9 @@ pub enum BuiltinLintDiag {
|
|||
InnerAttributeUnstable {
|
||||
is_macro: bool,
|
||||
},
|
||||
OutOfScopeMacroCalls {
|
||||
path: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
|
|
|
|||
|
|
@ -1817,11 +1817,11 @@ mod size_asserts {
|
|||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(BasicBlockData<'_>, 144);
|
||||
static_assert_size!(BasicBlockData<'_>, 128);
|
||||
static_assert_size!(LocalDecl<'_>, 40);
|
||||
static_assert_size!(SourceScopeData<'_>, 64);
|
||||
static_assert_size!(Statement<'_>, 32);
|
||||
static_assert_size!(Terminator<'_>, 112);
|
||||
static_assert_size!(Terminator<'_>, 96);
|
||||
static_assert_size!(VarDebugInfo<'_>, 88);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// reused across function calls without duplicating the contents.
|
||||
/// The span for each arg is also included
|
||||
/// (e.g. `a` and `b` in `x.foo(a, b)`).
|
||||
args: Vec<Spanned<Operand<'tcx>>>,
|
||||
args: Box<[Spanned<Operand<'tcx>>]>,
|
||||
/// Where the returned value will be written
|
||||
destination: Place<'tcx>,
|
||||
/// Where to go after this call returns. If none, the call necessarily diverges.
|
||||
|
|
@ -837,7 +837,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
template: &'tcx [InlineAsmTemplatePiece],
|
||||
|
||||
/// The operands for the inline assembly, as `Operand`s or `Place`s.
|
||||
operands: Vec<InlineAsmOperand<'tcx>>,
|
||||
operands: Box<[InlineAsmOperand<'tcx>]>,
|
||||
|
||||
/// Miscellaneous options for the inline assembly.
|
||||
options: InlineAsmOptions,
|
||||
|
|
@ -849,7 +849,7 @@ pub enum TerminatorKind<'tcx> {
|
|||
/// Valid targets for the inline assembly.
|
||||
/// The first element is the fallthrough destination, unless
|
||||
/// InlineAsmOptions::NORETURN is set.
|
||||
targets: Vec<BasicBlock>,
|
||||
targets: Box<[BasicBlock]>,
|
||||
|
||||
/// Action to be taken if the inline assembly unwinds. This is present
|
||||
/// if and only if InlineAsmOptions::MAY_UNWIND is set.
|
||||
|
|
@ -1561,6 +1561,6 @@ mod size_asserts {
|
|||
static_assert_size!(PlaceElem<'_>, 24);
|
||||
static_assert_size!(Rvalue<'_>, 40);
|
||||
static_assert_size!(StatementKind<'_>, 16);
|
||||
static_assert_size!(TerminatorKind<'_>, 96);
|
||||
static_assert_size!(TerminatorKind<'_>, 80);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
|
||||
let trait_generics = self.generics_of(trait_def_id);
|
||||
(
|
||||
ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)),
|
||||
ty::TraitRef::new_from_args(self, trait_def_id, args.truncate_to(self, trait_generics)),
|
||||
&args[trait_generics.count()..],
|
||||
)
|
||||
}
|
||||
|
|
@ -261,12 +261,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.check_args_compatible(def_id, args)
|
||||
}
|
||||
|
||||
fn check_and_mk_args(
|
||||
self,
|
||||
def_id: DefId,
|
||||
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
|
||||
) -> ty::GenericArgsRef<'tcx> {
|
||||
self.check_and_mk_args(def_id, args)
|
||||
fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) {
|
||||
self.debug_assert_args_compatible(def_id, args);
|
||||
}
|
||||
|
||||
fn intern_canonical_goal_evaluation_step(
|
||||
|
|
|
|||
|
|
@ -309,7 +309,8 @@ impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum SizeSkeleton<'tcx> {
|
||||
/// Any statically computable Layout.
|
||||
Known(Size),
|
||||
/// Alignment can be `None` if unknown.
|
||||
Known(Size, Option<Align>),
|
||||
|
||||
/// This is a generic const expression (i.e. N * 2), which may contain some parameters.
|
||||
/// It must be of type usize, and represents the size of a type in bytes.
|
||||
|
|
@ -339,7 +340,12 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
// First try computing a static layout.
|
||||
let err = match tcx.layout_of(param_env.and(ty)) {
|
||||
Ok(layout) => {
|
||||
return Ok(SizeSkeleton::Known(layout.size));
|
||||
if layout.abi.is_sized() {
|
||||
return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi)));
|
||||
} else {
|
||||
// Just to be safe, don't claim a known layout for unsized types.
|
||||
return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
|
||||
}
|
||||
}
|
||||
Err(err @ LayoutError::Unknown(_)) => err,
|
||||
// We can't extract SizeSkeleton info from other layout errors
|
||||
|
|
@ -389,19 +395,20 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
|
||||
let len_eval = len.try_eval_target_usize(tcx, param_env);
|
||||
if len_eval == Some(0) {
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
|
||||
}
|
||||
|
||||
match SizeSkeleton::compute(inner, tcx, param_env)? {
|
||||
// This may succeed because the multiplication of two types may overflow
|
||||
// but a single size of a nested array will not.
|
||||
SizeSkeleton::Known(s) => {
|
||||
SizeSkeleton::Known(s, a) => {
|
||||
if let Some(c) = len_eval {
|
||||
let size = s
|
||||
.bytes()
|
||||
.checked_mul(c)
|
||||
.ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
|
||||
// Alignment is unchanged by arrays.
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
|
||||
}
|
||||
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
|
||||
}
|
||||
|
|
@ -427,8 +434,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
for field in fields {
|
||||
let field = field?;
|
||||
match field {
|
||||
SizeSkeleton::Known(size) => {
|
||||
if size.bytes() > 0 {
|
||||
SizeSkeleton::Known(size, align) => {
|
||||
let is_1zst = size.bytes() == 0
|
||||
&& align.is_some_and(|align| align.bytes() == 1);
|
||||
if !is_1zst {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
|
@ -492,7 +501,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
|
||||
pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool {
|
||||
match (self, other) {
|
||||
(SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
|
||||
(SizeSkeleton::Known(a, _), SizeSkeleton::Known(b, _)) => a == b,
|
||||
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
|
||||
a == b
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,20 @@ impl<H, T> RawList<H, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, H, T: Copy> rustc_type_ir::inherent::SliceLike for &'a RawList<H, T> {
|
||||
type Item = T;
|
||||
|
||||
type IntoIter = iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
|
||||
|
||||
fn iter(self) -> Self::IntoIter {
|
||||
(*self).iter()
|
||||
}
|
||||
|
||||
fn as_slice(&self) -> &[Self::Item] {
|
||||
(*self).as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_list_empty {
|
||||
($header_ty:ty, $header_init:expr) => {
|
||||
impl<T> RawList<$header_ty, T> {
|
||||
|
|
|
|||
|
|
@ -499,7 +499,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
|
||||
#[inline]
|
||||
pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
||||
Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args))
|
||||
Ty::new_alias(tcx, ty::Opaque, AliasTy::new_from_args(tcx, def_id, args))
|
||||
}
|
||||
|
||||
/// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
|
||||
|
|
@ -669,6 +669,15 @@ impl<'tcx> Ty<'tcx> {
|
|||
Ty::new(tcx, Dynamic(obj, reg, repr))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_projection_from_args(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item_def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
Ty::new_alias(tcx, ty::Projection, AliasTy::new_from_args(tcx, item_def_id, args))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_projection(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
@ -1409,7 +1418,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
let assoc_items = tcx.associated_item_def_ids(
|
||||
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
|
||||
);
|
||||
Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
|
||||
Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => ty.discriminant_ty(tcx),
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
|||
.map(|arg|
|
||||
Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } )
|
||||
)
|
||||
.collect::<PResult<Vec<_>>>()?;
|
||||
.collect::<PResult<Box<[_]>>>()?;
|
||||
Ok(TerminatorKind::Call {
|
||||
func: fun,
|
||||
args,
|
||||
|
|
|
|||
|
|
@ -152,10 +152,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
source_info,
|
||||
TerminatorKind::Call {
|
||||
func: exchange_malloc,
|
||||
args: vec![
|
||||
args: [
|
||||
Spanned { node: Operand::Move(size), span: DUMMY_SP },
|
||||
Spanned { node: Operand::Move(align), span: DUMMY_SP },
|
||||
],
|
||||
]
|
||||
.into(),
|
||||
destination: storage,
|
||||
target: Some(success),
|
||||
unwind: UnwindAction::Continue,
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
|
||||
let fun = unpack!(block = this.as_local_operand(block, fun));
|
||||
let args: Vec<_> = args
|
||||
let args: Box<[_]> = args
|
||||
.into_iter()
|
||||
.copied()
|
||||
.map(|arg| Spanned {
|
||||
|
|
@ -485,7 +485,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
operands,
|
||||
options,
|
||||
line_spans,
|
||||
targets,
|
||||
targets: targets.into_boxed_slice(),
|
||||
unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
UnwindAction::Continue
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
user_ty: None,
|
||||
const_: method,
|
||||
})),
|
||||
args: vec![Spanned { node: Operand::Move(ref_src), span }],
|
||||
args: [Spanned { node: Operand::Move(ref_src), span }].into(),
|
||||
destination: temp,
|
||||
target: Some(target_block),
|
||||
unwind: UnwindAction::Continue,
|
||||
|
|
@ -486,10 +486,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
const_: method,
|
||||
})),
|
||||
args: vec![
|
||||
args: [
|
||||
Spanned { node: Operand::Copy(val), span: DUMMY_SP },
|
||||
Spanned { node: expect, span: DUMMY_SP },
|
||||
],
|
||||
]
|
||||
.into(),
|
||||
destination: eq_result,
|
||||
target: Some(eq_block),
|
||||
unwind: UnwindAction::Continue,
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
ty::TraitRef::new(
|
||||
ty::TraitRef::new_from_args(
|
||||
tcx,
|
||||
partial_eq_trait_id,
|
||||
tcx.with_opt_host_effect_param(
|
||||
|
|
|
|||
|
|
@ -650,10 +650,8 @@ where
|
|||
[ty.into()],
|
||||
self.source_info.span,
|
||||
),
|
||||
args: vec![Spanned {
|
||||
node: Operand::Move(Place::from(ref_place)),
|
||||
span: DUMMY_SP,
|
||||
}],
|
||||
args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }]
|
||||
.into(),
|
||||
destination: unit_temp,
|
||||
target: Some(succ),
|
||||
unwind: unwind.into_action(),
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
|
|||
2,
|
||||
mir::TerminatorKind::Call {
|
||||
func: mir::Operand::Copy(dummy_place.clone()),
|
||||
args: vec![],
|
||||
args: [].into(),
|
||||
destination: dummy_place.clone(),
|
||||
target: Some(mir::START_BLOCK),
|
||||
unwind: mir::UnwindAction::Continue,
|
||||
|
|
@ -48,7 +48,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
|
|||
4,
|
||||
mir::TerminatorKind::Call {
|
||||
func: mir::Operand::Copy(dummy_place.clone()),
|
||||
args: vec![],
|
||||
args: [].into(),
|
||||
destination: dummy_place.clone(),
|
||||
target: Some(mir::START_BLOCK),
|
||||
unwind: mir::UnwindAction::Continue,
|
||||
|
|
|
|||
|
|
@ -677,8 +677,8 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
|
||||
fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local {
|
||||
let terminator = bb_data.terminator.take().unwrap();
|
||||
if let TerminatorKind::Call { mut args, destination, target, .. } = terminator.kind {
|
||||
let arg = args.pop().unwrap();
|
||||
if let TerminatorKind::Call { args, destination, target, .. } = terminator.kind {
|
||||
let [arg] = *Box::try_from(args).unwrap();
|
||||
let local = arg.node.place().unwrap().local;
|
||||
|
||||
let arg = Rvalue::Use(arg.node);
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ impl<'tcx> MockBlocks<'tcx> {
|
|||
some_from_block,
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Copy(self.dummy_place.clone()),
|
||||
args: vec![],
|
||||
args: [].into(),
|
||||
destination: self.dummy_place.clone(),
|
||||
target: Some(TEMP_BLOCK),
|
||||
unwind: UnwindAction::Continue,
|
||||
|
|
|
|||
|
|
@ -624,8 +624,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
};
|
||||
|
||||
// Copy the arguments if needed.
|
||||
let args: Vec<_> =
|
||||
self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
|
||||
let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
|
||||
|
||||
let mut integrator = Integrator {
|
||||
args: &args,
|
||||
|
|
@ -736,12 +735,12 @@ impl<'tcx> Inliner<'tcx> {
|
|||
|
||||
fn make_call_args(
|
||||
&self,
|
||||
args: Vec<Spanned<Operand<'tcx>>>,
|
||||
args: Box<[Spanned<Operand<'tcx>>]>,
|
||||
callsite: &CallSite<'tcx>,
|
||||
caller_body: &mut Body<'tcx>,
|
||||
callee_body: &Body<'tcx>,
|
||||
return_block: Option<BasicBlock>,
|
||||
) -> Vec<Local> {
|
||||
) -> Box<[Local]> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
// There is a bit of a mismatch between the *caller* of a closure and the *callee*.
|
||||
|
|
@ -768,7 +767,8 @@ impl<'tcx> Inliner<'tcx> {
|
|||
//
|
||||
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
|
||||
if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
|
||||
let mut args = args.into_iter();
|
||||
// FIXME(edition_2024): switch back to a normal method call.
|
||||
let mut args = <_>::into_iter(args);
|
||||
let self_ = self.create_temp_if_necessary(
|
||||
args.next().unwrap().node,
|
||||
callsite,
|
||||
|
|
@ -802,7 +802,8 @@ impl<'tcx> Inliner<'tcx> {
|
|||
|
||||
closure_ref_arg.chain(tuple_tmp_args).collect()
|
||||
} else {
|
||||
args.into_iter()
|
||||
// FIXME(edition_2024): switch back to a normal method call.
|
||||
<_>::into_iter(args)
|
||||
.map(|a| self.create_temp_if_necessary(a.node, callsite, caller_body, return_block))
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! Performs various peephole optimizations.
|
||||
|
||||
use crate::simplify::simplify_duplicate_switch_targets;
|
||||
use crate::take_array;
|
||||
use rustc_ast::attr;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::*;
|
||||
|
|
@ -285,7 +286,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
|||
return;
|
||||
}
|
||||
|
||||
let Some(arg_place) = args.pop().unwrap().node.place() else { return };
|
||||
let Ok([arg]) = take_array(args) else { return };
|
||||
let Some(arg_place) = arg.node.place() else { return };
|
||||
|
||||
statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
|
|
|
|||
|
|
@ -160,8 +160,9 @@ fn remap_mir_for_const_eval_select<'tcx>(
|
|||
} if let ty::FnDef(def_id, _) = *const_.ty().kind()
|
||||
&& tcx.is_intrinsic(def_id, sym::const_eval_select) =>
|
||||
{
|
||||
let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
|
||||
std::mem::take(args).try_into().unwrap();
|
||||
let Ok([tupled_args, called_in_const, called_at_rt]) = take_array(args) else {
|
||||
unreachable!()
|
||||
};
|
||||
let ty = tupled_args.node.ty(&body.local_decls, tcx);
|
||||
let fields = ty.tuple_fields();
|
||||
let num_args = fields.len();
|
||||
|
|
@ -211,6 +212,11 @@ fn remap_mir_for_const_eval_select<'tcx>(
|
|||
body
|
||||
}
|
||||
|
||||
fn take_array<T, const N: usize>(b: &mut Box<[T]>) -> Result<[T; N], Box<[T]>> {
|
||||
let b: Box<[T; N]> = std::mem::take(b).try_into()?;
|
||||
Ok(*b)
|
||||
}
|
||||
|
||||
fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
tcx.mir_keys(()).contains(&def_id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Lowers intrinsic calls
|
||||
|
||||
use crate::take_array;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -50,42 +51,34 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
sym::copy_nonoverlapping => {
|
||||
let target = target.unwrap();
|
||||
let mut args = args.drain(..);
|
||||
let Ok([src, dst, count]) = take_array(args) else {
|
||||
bug!("Wrong arguments for copy_non_overlapping intrinsic");
|
||||
};
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Intrinsic(Box::new(
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(
|
||||
rustc_middle::mir::CopyNonOverlapping {
|
||||
src: args.next().unwrap().node,
|
||||
dst: args.next().unwrap().node,
|
||||
count: args.next().unwrap().node,
|
||||
src: src.node,
|
||||
dst: dst.node,
|
||||
count: count.node,
|
||||
},
|
||||
),
|
||||
)),
|
||||
});
|
||||
assert_eq!(
|
||||
args.next(),
|
||||
None,
|
||||
"Extra argument for copy_non_overlapping intrinsic"
|
||||
);
|
||||
drop(args);
|
||||
terminator.kind = TerminatorKind::Goto { target };
|
||||
}
|
||||
sym::assume => {
|
||||
let target = target.unwrap();
|
||||
let mut args = args.drain(..);
|
||||
let Ok([arg]) = take_array(args) else {
|
||||
bug!("Wrong arguments for assume intrinsic");
|
||||
};
|
||||
block.statements.push(Statement {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Intrinsic(Box::new(
|
||||
NonDivergingIntrinsic::Assume(args.next().unwrap().node),
|
||||
NonDivergingIntrinsic::Assume(arg.node),
|
||||
)),
|
||||
});
|
||||
assert_eq!(
|
||||
args.next(),
|
||||
None,
|
||||
"Extra argument for copy_non_overlapping intrinsic"
|
||||
);
|
||||
drop(args);
|
||||
terminator.kind = TerminatorKind::Goto { target };
|
||||
}
|
||||
sym::wrapping_add
|
||||
|
|
@ -100,13 +93,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
| sym::unchecked_shl
|
||||
| sym::unchecked_shr => {
|
||||
let target = target.unwrap();
|
||||
let lhs;
|
||||
let rhs;
|
||||
{
|
||||
let mut args = args.drain(..);
|
||||
lhs = args.next().unwrap();
|
||||
rhs = args.next().unwrap();
|
||||
}
|
||||
let Ok([lhs, rhs]) = take_array(args) else {
|
||||
bug!("Wrong arguments for {} intrinsic", intrinsic.name);
|
||||
};
|
||||
let bin_op = match intrinsic.name {
|
||||
sym::wrapping_add => BinOp::Add,
|
||||
sym::wrapping_sub => BinOp::Sub,
|
||||
|
|
@ -132,13 +121,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
|
||||
if let Some(target) = *target {
|
||||
let lhs;
|
||||
let rhs;
|
||||
{
|
||||
let mut args = args.drain(..);
|
||||
lhs = args.next().unwrap();
|
||||
rhs = args.next().unwrap();
|
||||
}
|
||||
let Ok([lhs, rhs]) = take_array(args) else {
|
||||
bug!("Wrong arguments for {} intrinsic", intrinsic.name);
|
||||
};
|
||||
let bin_op = match intrinsic.name {
|
||||
sym::add_with_overflow => BinOp::AddWithOverflow,
|
||||
sym::sub_with_overflow => BinOp::SubWithOverflow,
|
||||
|
|
@ -174,7 +159,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
}
|
||||
sym::read_via_copy => {
|
||||
let [arg] = args.as_slice() else {
|
||||
let Ok([arg]) = take_array(args) else {
|
||||
span_bug!(terminator.source_info.span, "Wrong number of arguments");
|
||||
};
|
||||
let derefed_place = if let Some(place) = arg.node.place()
|
||||
|
|
@ -207,7 +192,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
sym::write_via_move => {
|
||||
let target = target.unwrap();
|
||||
let Ok([ptr, val]) = <[_; 2]>::try_from(std::mem::take(args)) else {
|
||||
let Ok([ptr, val]) = take_array(args) else {
|
||||
span_bug!(
|
||||
terminator.source_info.span,
|
||||
"Wrong number of arguments for write_via_move intrinsic",
|
||||
|
|
@ -247,7 +232,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
sym::offset => {
|
||||
let target = target.unwrap();
|
||||
let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
|
||||
let Ok([ptr, delta]) = take_array(args) else {
|
||||
span_bug!(
|
||||
terminator.source_info.span,
|
||||
"Wrong number of arguments for offset intrinsic",
|
||||
|
|
@ -264,7 +249,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
sym::transmute | sym::transmute_unchecked => {
|
||||
let dst_ty = destination.ty(local_decls, tcx).ty;
|
||||
let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
|
||||
let Ok([arg]) = take_array(args) else {
|
||||
span_bug!(
|
||||
terminator.source_info.span,
|
||||
"Wrong number of arguments for transmute intrinsic",
|
||||
|
|
@ -289,7 +274,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
}
|
||||
sym::aggregate_raw_ptr => {
|
||||
let Ok([data, meta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
|
||||
let Ok([data, meta]) = take_array(args) else {
|
||||
span_bug!(
|
||||
terminator.source_info.span,
|
||||
"Wrong number of arguments for aggregate_raw_ptr intrinsic",
|
||||
|
|
@ -317,7 +302,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||
terminator.kind = TerminatorKind::Goto { target };
|
||||
}
|
||||
sym::ptr_metadata => {
|
||||
let Ok([ptr]) = <[_; 1]>::try_from(std::mem::take(args)) else {
|
||||
let Ok([ptr]) = take_array(args) else {
|
||||
span_bug!(
|
||||
terminator.source_info.span,
|
||||
"Wrong number of arguments for ptr_metadata intrinsic",
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
|||
vec![statement],
|
||||
TerminatorKind::Call {
|
||||
func,
|
||||
args: vec![Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }],
|
||||
args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
|
||||
destination: dest,
|
||||
target: Some(next),
|
||||
unwind: UnwindAction::Cleanup(cleanup),
|
||||
|
|
@ -843,7 +843,7 @@ fn build_call_shim<'tcx>(
|
|||
};
|
||||
|
||||
// BB #0
|
||||
let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect::<Vec<_>>();
|
||||
let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
|
||||
block(
|
||||
&mut blocks,
|
||||
statements,
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ where
|
|||
};
|
||||
|
||||
for assumption in
|
||||
self.cx().item_bounds(alias_ty.def_id).iter_instantiated(self.cx(), &alias_ty.args)
|
||||
self.cx().item_bounds(alias_ty.def_id).iter_instantiated(self.cx(), alias_ty.args)
|
||||
{
|
||||
candidates.extend(G::probe_and_consider_implied_clause(
|
||||
self,
|
||||
|
|
@ -603,7 +603,7 @@ where
|
|||
// Consider all of the auto-trait and projection bounds, which don't
|
||||
// need to be recorded as a `BuiltinImplSource::Object` since they don't
|
||||
// really have a vtable base...
|
||||
for bound in bounds {
|
||||
for bound in bounds.iter() {
|
||||
match bound.skip_binder() {
|
||||
ty::ExistentialPredicate::Trait(_) => {
|
||||
// Skip principal
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ where
|
|||
|
||||
ty::Tuple(tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
Ok(tys.into_iter().map(ty::Binder::dummy).collect())
|
||||
Ok(tys.iter().map(ty::Binder::dummy).collect())
|
||||
}
|
||||
|
||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
||||
|
|
@ -79,23 +79,21 @@ where
|
|||
.cx()
|
||||
.bound_coroutine_hidden_types(def_id)
|
||||
.into_iter()
|
||||
.map(|bty| bty.instantiate(tcx, &args))
|
||||
.map(|bty| bty.instantiate(tcx, args))
|
||||
.collect()),
|
||||
|
||||
// For `PhantomData<T>`, we pass `T`.
|
||||
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
|
||||
|
||||
ty::Adt(def, args) => Ok(def
|
||||
.all_field_tys(tcx)
|
||||
.iter_instantiated(tcx, &args)
|
||||
.map(ty::Binder::dummy)
|
||||
.collect()),
|
||||
ty::Adt(def, args) => {
|
||||
Ok(def.all_field_tys(tcx).iter_instantiated(tcx, args).map(ty::Binder::dummy).collect())
|
||||
}
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
||||
// We can resolve the `impl Trait` to its concrete type,
|
||||
// which enforces a DAG between the functions requiring
|
||||
// the auto trait bounds in question.
|
||||
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, &args))])
|
||||
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -147,7 +145,7 @@ where
|
|||
|
||||
// impl Sized for ()
|
||||
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
|
||||
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |&ty| vec![ty::Binder::dummy(ty)])),
|
||||
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])),
|
||||
|
||||
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
|
||||
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
|
||||
|
|
@ -160,7 +158,7 @@ where
|
|||
// if the ADT is sized for all possible args.
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
|
||||
Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), &args))])
|
||||
Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), args))])
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
|
@ -213,7 +211,7 @@ where
|
|||
}
|
||||
|
||||
// impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
|
||||
ty::Tuple(tys) => Ok(tys.into_iter().map(ty::Binder::dummy).collect()),
|
||||
ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
|
||||
|
||||
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
|
||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
||||
|
|
@ -242,7 +240,7 @@ where
|
|||
.cx()
|
||||
.bound_coroutine_hidden_types(def_id)
|
||||
.into_iter()
|
||||
.map(|bty| bty.instantiate(ecx.cx(), &args))
|
||||
.map(|bty| bty.instantiate(ecx.cx(), args))
|
||||
.collect()),
|
||||
}
|
||||
}
|
||||
|
|
@ -259,8 +257,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
let sig = tcx.fn_sig(def_id);
|
||||
if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) {
|
||||
Ok(Some(
|
||||
sig.instantiate(tcx, &args)
|
||||
.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output())),
|
||||
sig.instantiate(tcx, args)
|
||||
.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
|
||||
))
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
|
|
@ -269,7 +267,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
|
||||
ty::FnPtr(sig) => {
|
||||
if sig.is_fn_trait_compatible() {
|
||||
Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output()))))
|
||||
Ok(Some(
|
||||
sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())),
|
||||
))
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
}
|
||||
|
|
@ -292,7 +292,9 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
|
||||
Ok(Some(
|
||||
closure_args.sig().map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())),
|
||||
))
|
||||
}
|
||||
|
||||
// Coroutine-closures don't implement `Fn` traits the normal way.
|
||||
|
|
@ -470,7 +472,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||
Ok((
|
||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||
tupled_inputs_ty: Ty::new_tup(tcx, &sig.inputs()),
|
||||
tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs().as_slice()),
|
||||
output_coroutine_ty: sig.output(),
|
||||
coroutine_return_ty: future_output_ty,
|
||||
}),
|
||||
|
|
@ -521,7 +523,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
|||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||
Ok((
|
||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||
tupled_inputs_ty: sig.inputs()[0],
|
||||
tupled_inputs_ty: sig.inputs().get(0).unwrap(),
|
||||
output_coroutine_ty: sig.output(),
|
||||
coroutine_return_ty: future_output_ty,
|
||||
}),
|
||||
|
|
@ -669,7 +671,7 @@ where
|
|||
let tcx = ecx.cx();
|
||||
let mut requirements = vec![];
|
||||
requirements
|
||||
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args));
|
||||
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, trait_ref.args));
|
||||
|
||||
// FIXME(associated_const_equality): Also add associated consts to
|
||||
// the requirements here.
|
||||
|
|
@ -680,13 +682,12 @@ where
|
|||
continue;
|
||||
}
|
||||
|
||||
requirements.extend(
|
||||
tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, &trait_ref.args),
|
||||
);
|
||||
requirements
|
||||
.extend(tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, trait_ref.args));
|
||||
}
|
||||
|
||||
let mut replace_projection_with = HashMap::default();
|
||||
for bound in object_bounds {
|
||||
for bound in object_bounds.iter() {
|
||||
if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
|
||||
let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
|
||||
let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
|
||||
|
|
|
|||
|
|
@ -267,7 +267,9 @@ where
|
|||
// We therefore instantiate the existential variable in the canonical response with the
|
||||
// inference variable of the input right away, which is more performant.
|
||||
let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
|
||||
for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
|
||||
for (original_value, result_value) in
|
||||
iter::zip(original_values, var_values.var_values.iter())
|
||||
{
|
||||
match result_value.kind() {
|
||||
ty::GenericArgKind::Type(t) => {
|
||||
if let ty::Bound(debruijn, b) = t.kind() {
|
||||
|
|
@ -291,7 +293,7 @@ where
|
|||
}
|
||||
|
||||
let var_values = delegate.cx().mk_args_from_iter(
|
||||
response.variables.into_iter().enumerate().map(|(index, info)| {
|
||||
response.variables.iter().enumerate().map(|(index, info)| {
|
||||
if info.universe() != ty::UniverseIndex::ROOT {
|
||||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all (see the FIXME at the start of this method), we have to deal with
|
||||
|
|
@ -344,7 +346,7 @@ where
|
|||
) {
|
||||
assert_eq!(original_values.len(), var_values.len());
|
||||
|
||||
for (&orig, response) in iter::zip(original_values, var_values.var_values) {
|
||||
for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
|
||||
let goals =
|
||||
delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap();
|
||||
assert!(goals.is_empty());
|
||||
|
|
@ -413,7 +415,8 @@ where
|
|||
// In case any fresh inference variables have been created between `state`
|
||||
// and the previous instantiation, extend `orig_values` for it.
|
||||
assert!(orig_values.len() <= state.value.var_values.len());
|
||||
for &arg in &state.value.var_values.var_values[orig_values.len()..state.value.var_values.len()]
|
||||
for &arg in &state.value.var_values.var_values.as_slice()
|
||||
[orig_values.len()..state.value.var_values.len()]
|
||||
{
|
||||
// FIXME: This is so ugly.
|
||||
let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span);
|
||||
|
|
|
|||
|
|
@ -787,7 +787,7 @@ where
|
|||
// Alternatively we could modify `Equate` for this case by adding another
|
||||
// variant to `StructurallyRelateAliases`.
|
||||
let identity_args = self.fresh_args_for_item(alias.def_id);
|
||||
let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args);
|
||||
let rigid_ctor = ty::AliasTerm::new_from_args(tcx, alias.def_id, identity_args);
|
||||
let ctor_term = rigid_ctor.to_term(tcx);
|
||||
let obligations =
|
||||
self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
|
||||
|
|
@ -875,7 +875,7 @@ where
|
|||
|
||||
pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
|
||||
let args = self.delegate.fresh_args_for_item(def_id);
|
||||
for arg in args {
|
||||
for arg in args.iter() {
|
||||
self.inspect.add_var_value(arg);
|
||||
}
|
||||
args
|
||||
|
|
@ -979,7 +979,7 @@ where
|
|||
result: *result,
|
||||
})
|
||||
.enter(|ecx| {
|
||||
for (a, b) in std::iter::zip(candidate_key.args, key.args) {
|
||||
for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) {
|
||||
ecx.eq(param_env, a, b)?;
|
||||
}
|
||||
ecx.eq(param_env, candidate_ty, ty)?;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::{self as ty, Interner};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ where
|
|||
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
}
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
self.cx().type_of(uv.def).instantiate(self.cx(), &uv.args)
|
||||
self.cx().type_of(uv.def).instantiate(self.cx(), uv.args)
|
||||
}
|
||||
ty::ConstKind::Expr(_) => unimplemented!(
|
||||
"`feature(generic_const_exprs)` is not supported in the new trait solver"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ where
|
|||
self.eq(
|
||||
goal.param_env,
|
||||
inherent.self_ty(),
|
||||
tcx.type_of(impl_def_id).instantiate(tcx, &impl_args),
|
||||
tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
|
||||
)?;
|
||||
|
||||
// Equate IAT with the RHS of the project goal
|
||||
|
|
@ -44,11 +44,11 @@ where
|
|||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(inherent.def_id)
|
||||
.iter_instantiated(tcx, &inherent_args)
|
||||
.iter_instantiated(tcx, inherent_args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
);
|
||||
|
||||
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, &inherent_args);
|
||||
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args);
|
||||
self.instantiate_normalizes_to_term(goal, normalized.into());
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ where
|
|||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, &goal.predicate.alias.args)
|
||||
.iter_instantiated(tcx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
);
|
||||
|
||||
|
|
@ -163,13 +163,13 @@ where
|
|||
|
||||
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
||||
let impl_args = ecx.fresh_args_for_item(impl_def_id);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
|
||||
|
||||
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
|
||||
|
||||
let where_clause_bounds = tcx
|
||||
.predicates_of(impl_def_id)
|
||||
.iter_instantiated(tcx, &impl_args)
|
||||
.iter_instantiated(tcx, impl_args)
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ where
|
|||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.own_predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, &goal.predicate.alias.args)
|
||||
.iter_instantiated(tcx, goal.predicate.alias.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
);
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ where
|
|||
kind => panic!("expected projection, found {kind:?}"),
|
||||
};
|
||||
|
||||
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, &target_args));
|
||||
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, target_args));
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
|
@ -467,7 +467,7 @@ where
|
|||
tupled_inputs_ty,
|
||||
tupled_upvars_ty,
|
||||
coroutine_captures_by_ref_ty,
|
||||
] = **goal.predicate.alias.args
|
||||
] = *goal.predicate.alias.args.as_slice()
|
||||
else {
|
||||
panic!();
|
||||
};
|
||||
|
|
@ -567,14 +567,14 @@ where
|
|||
ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(tcx) {
|
||||
None => Ty::new_unit(tcx),
|
||||
Some(tail_ty) => {
|
||||
Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, &args)])
|
||||
Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, args)])
|
||||
}
|
||||
},
|
||||
ty::Adt(_, _) => Ty::new_unit(tcx),
|
||||
|
||||
ty::Tuple(elements) => match elements.last() {
|
||||
None => Ty::new_unit(tcx),
|
||||
Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
|
||||
Some(tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]),
|
||||
},
|
||||
|
||||
ty::Infer(
|
||||
|
|
@ -895,7 +895,7 @@ where
|
|||
} else {
|
||||
let target_args = self.fresh_args_for_item(target_container_def_id);
|
||||
let target_trait_ref =
|
||||
tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, &target_args);
|
||||
tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, target_args);
|
||||
// Relate source impl to target impl by equating trait refs.
|
||||
self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?;
|
||||
// Also add predicates since they may be needed to constrain the
|
||||
|
|
@ -903,7 +903,7 @@ where
|
|||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(target_container_def_id)
|
||||
.iter_instantiated(tcx, &target_args)
|
||||
.iter_instantiated(tcx, target_args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
);
|
||||
goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ where
|
|||
}
|
||||
(Reveal::All, _) => {
|
||||
// FIXME: Add an assertion that opaque type storage is empty.
|
||||
let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, &opaque_ty.args);
|
||||
let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args);
|
||||
self.eq(goal.param_env, expected, actual)?;
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ pub fn uses_unique_placeholders_ignoring_regions<I: Interner>(
|
|||
args: I::GenericArgs,
|
||||
) -> Result<(), NotUniqueParam<I>> {
|
||||
let mut seen = GrowableBitSet::default();
|
||||
for arg in args {
|
||||
for arg in args.iter() {
|
||||
match arg.kind() {
|
||||
// Ignore regions, since we can't resolve those in a canonicalized
|
||||
// query in the trait solver.
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@ where
|
|||
self.add_goals(
|
||||
GoalSource::Misc,
|
||||
tcx.predicates_of(weak_ty.def_id)
|
||||
.iter_instantiated(tcx, &weak_ty.args)
|
||||
.iter_instantiated(tcx, weak_ty.args)
|
||||
.map(|pred| goal.with(tcx, pred)),
|
||||
);
|
||||
|
||||
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, &weak_ty.args);
|
||||
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
||||
self.instantiate_normalizes_to_term(goal, actual.into());
|
||||
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ where
|
|||
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
|
||||
let impl_args = ecx.fresh_args_for_item(impl_def_id);
|
||||
ecx.record_impl_args(impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, &impl_args);
|
||||
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
|
||||
|
||||
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
|
||||
let where_clause_bounds = tcx
|
||||
.predicates_of(impl_def_id)
|
||||
.iter_instantiated(tcx, &impl_args)
|
||||
.iter_instantiated(tcx, impl_args)
|
||||
.map(|pred| goal.with(tcx, pred));
|
||||
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
|
||||
|
||||
|
|
@ -186,7 +186,7 @@ where
|
|||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
let nested_obligations = tcx
|
||||
.predicates_of(goal.predicate.def_id())
|
||||
.iter_instantiated(tcx, &goal.predicate.trait_ref.args)
|
||||
.iter_instantiated(tcx, goal.predicate.trait_ref.args)
|
||||
.map(|p| goal.with(tcx, p));
|
||||
// FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
|
||||
ecx.add_goals(GoalSource::Misc, nested_obligations);
|
||||
|
|
@ -373,7 +373,7 @@ where
|
|||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
|
||||
let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
|
||||
panic!();
|
||||
};
|
||||
|
||||
|
|
@ -783,7 +783,7 @@ where
|
|||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
b_data.into_iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
|
||||
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
|
||||
);
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
|
|
@ -851,7 +851,7 @@ where
|
|||
};
|
||||
|
||||
self.probe_trait_candidate(source).enter(|ecx| {
|
||||
for bound in b_data {
|
||||
for bound in b_data.iter() {
|
||||
match bound.skip_binder() {
|
||||
// Check that a's supertrait (upcast_principal) is compatible
|
||||
// with the target (b_ty).
|
||||
|
|
@ -953,18 +953,15 @@ where
|
|||
|
||||
let tail_field_ty = def.struct_tail_ty(tcx).unwrap();
|
||||
|
||||
let a_tail_ty = tail_field_ty.instantiate(tcx, &a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(tcx, &b_args);
|
||||
let a_tail_ty = tail_field_ty.instantiate(tcx, a_args);
|
||||
let b_tail_ty = tail_field_ty.instantiate(tcx, b_args);
|
||||
|
||||
// Instantiate just the unsizing params from B into A. The type after
|
||||
// this instantiation must be equal to B. This is so we don't unsize
|
||||
// unrelated type parameters.
|
||||
let new_a_args = tcx.mk_args_from_iter(
|
||||
a_args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, a)| if unsizing_params.contains(i as u32) { b_args[i] } else { *a }),
|
||||
);
|
||||
let new_a_args = tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
|
||||
if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
|
||||
}));
|
||||
let unsized_a_ty = Ty::new_adt(tcx, def, new_a_args);
|
||||
|
||||
// Finally, we require that `TailA: Unsize<TailB>` for the tail field
|
||||
|
|
@ -1005,7 +1002,7 @@ where
|
|||
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
|
||||
|
||||
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||
let &b_last_ty = b_tys.last().unwrap();
|
||||
let b_last_ty = b_tys.last().unwrap();
|
||||
|
||||
// Instantiate just the tail field of B., and require that they're equal.
|
||||
let unsized_a_ty =
|
||||
|
|
|
|||
|
|
@ -322,9 +322,8 @@ error: foo
|
|||
--> test.rs:3:3
|
||||
|
|
||||
3 | X0 Y0
|
||||
| ___^__-
|
||||
| |___|
|
||||
| ||
|
||||
| ____^ -
|
||||
| | ______|
|
||||
4 | || X1 Y1
|
||||
5 | || X2 Y2
|
||||
| ||____^__- `Y` is a good letter too
|
||||
|
|
@ -361,9 +360,8 @@ error: foo
|
|||
--> test.rs:3:3
|
||||
|
|
||||
3 | X0 Y0
|
||||
| ___^__-
|
||||
| |___|
|
||||
| ||
|
||||
| ____^ -
|
||||
| | ______|
|
||||
4 | || Y1 X1
|
||||
| ||____-__^ `X` is a good letter
|
||||
| |____|
|
||||
|
|
@ -445,10 +443,9 @@ error: foo
|
|||
--> test.rs:3:3
|
||||
|
|
||||
3 | X0 Y0 Z0
|
||||
| ___^__-__-
|
||||
| |___|__|
|
||||
| ||___|
|
||||
| |||
|
||||
| _____^ - -
|
||||
| | _______| |
|
||||
| || _________|
|
||||
4 | ||| X1 Y1 Z1
|
||||
5 | ||| X2 Y2 Z2
|
||||
| |||____^__-__- `Z` label
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ use crate::{errors, parse_in};
|
|||
|
||||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::DelimSpan;
|
||||
use rustc_ast::MetaItemKind;
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
|
||||
use rustc_ast::{
|
||||
self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemKind,
|
||||
NestedMetaItem, Safety,
|
||||
};
|
||||
use rustc_errors::{Applicability, FatalError, PResult};
|
||||
use rustc_feature::{
|
||||
AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
|
||||
|
|
@ -184,9 +186,13 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim
|
|||
|
||||
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
|
||||
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
|
||||
let is_one_allowed_subword = |items: &[NestedMetaItem]| match items {
|
||||
[item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)),
|
||||
_ => false,
|
||||
};
|
||||
match meta {
|
||||
MetaItemKind::Word => template.word,
|
||||
MetaItemKind::List(..) => template.list.is_some(),
|
||||
MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items),
|
||||
MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(),
|
||||
MetaItemKind::NameValue(..) => false,
|
||||
}
|
||||
|
|
@ -230,6 +236,7 @@ fn emit_malformed_attribute(
|
|||
if let Some(descr) = template.list {
|
||||
suggestions.push(format!("#{inner}[{name}({descr})]"));
|
||||
}
|
||||
suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
|
||||
if let Some(descr) = template.name_value_str {
|
||||
suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,18 +103,9 @@ passes_continue_labeled_block =
|
|||
.label = labeled blocks cannot be `continue`'d
|
||||
.block_label = labeled block the `continue` points to
|
||||
|
||||
passes_coverage_fn_defn =
|
||||
`#[coverage]` may only be applied to function definitions
|
||||
|
||||
passes_coverage_ignored_function_prototype =
|
||||
`#[coverage]` is ignored on function prototypes
|
||||
|
||||
passes_coverage_not_coverable =
|
||||
`#[coverage]` must be applied to coverable code
|
||||
.label = not coverable code
|
||||
|
||||
passes_coverage_propagate =
|
||||
`#[coverage]` does not propagate into items and must be applied to the contained functions directly
|
||||
passes_coverage_not_fn_or_closure =
|
||||
attribute should be applied to a function definition or closure
|
||||
.label = not a function or closure
|
||||
|
||||
passes_dead_codes =
|
||||
{ $multiple ->
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
|
||||
}
|
||||
[sym::inline] => self.check_inline(hir_id, attr, span, target),
|
||||
[sym::coverage] => self.check_coverage(hir_id, attr, span, target),
|
||||
[sym::coverage] => self.check_coverage(attr, span, target),
|
||||
[sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target),
|
||||
[sym::marker] => self.check_marker(hir_id, attr, span, target),
|
||||
[sym::target_feature] => {
|
||||
|
|
@ -369,47 +369,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks if a `#[coverage]` is applied directly to a function
|
||||
fn check_coverage(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
/// Checks that `#[coverage(..)]` is applied to a function or closure.
|
||||
fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
match target {
|
||||
// #[coverage] on function is fine
|
||||
// #[coverage(..)] on function is fine
|
||||
Target::Fn
|
||||
| Target::Closure
|
||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
||||
|
||||
// function prototypes can't be covered
|
||||
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::IgnoredCoverageFnProto,
|
||||
);
|
||||
true
|
||||
}
|
||||
|
||||
Target::Mod | Target::ForeignMod | Target::Impl | Target::Trait => {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::IgnoredCoveragePropagate,
|
||||
);
|
||||
true
|
||||
}
|
||||
|
||||
Target::Expression | Target::Statement | Target::Arm => {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::IgnoredCoverageFnDefn,
|
||||
);
|
||||
true
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::IgnoredCoverageNotCoverable {
|
||||
self.dcx().emit_err(errors::CoverageNotFnOrClosure {
|
||||
attr_span: attr.span,
|
||||
defn_span: span,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1010,6 +1010,22 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
parent_item: Option<LocalDefId>,
|
||||
report_on: ReportOn,
|
||||
) {
|
||||
fn get_parent_if_enum_variant<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
may_variant: LocalDefId,
|
||||
) -> LocalDefId {
|
||||
if let Node::Variant(_) = tcx.hir_node_by_def_id(may_variant)
|
||||
&& let Some(enum_did) = tcx.opt_parent(may_variant.to_def_id())
|
||||
&& let Some(enum_local_id) = enum_did.as_local()
|
||||
&& let Node::Item(item) = tcx.hir_node_by_def_id(enum_local_id)
|
||||
&& let ItemKind::Enum(_, _) = item.kind
|
||||
{
|
||||
enum_local_id
|
||||
} else {
|
||||
may_variant
|
||||
}
|
||||
}
|
||||
|
||||
let Some(&first_item) = dead_codes.first() else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -1053,6 +1069,9 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
};
|
||||
|
||||
let encl_def_id = parent_item.unwrap_or(first_item.def_id);
|
||||
// If parent of encl_def_id is an enum, use the parent ID intead.
|
||||
let encl_def_id = get_parent_if_enum_variant(tcx, encl_def_id);
|
||||
|
||||
let ignored_derived_impls =
|
||||
if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
|
||||
let trait_list = ign_traits
|
||||
|
|
|
|||
|
|
@ -60,21 +60,9 @@ pub struct InlineNotFnOrClosure {
|
|||
pub defn_span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_coverage_ignored_function_prototype)]
|
||||
pub struct IgnoredCoverageFnProto;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_coverage_propagate)]
|
||||
pub struct IgnoredCoveragePropagate;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_coverage_fn_defn)]
|
||||
pub struct IgnoredCoverageFnDefn;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_coverage_not_coverable, code = E0788)]
|
||||
pub struct IgnoredCoverageNotCoverable {
|
||||
#[diag(passes_coverage_not_fn_or_closure, code = E0788)]
|
||||
pub struct CoverageNotFnOrClosure {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
#[label]
|
||||
|
|
|
|||
|
|
@ -301,9 +301,12 @@ impl<HCX> ToStableHashKey<HCX> for WorkProductId {
|
|||
self.hash
|
||||
}
|
||||
}
|
||||
unsafe impl StableOrd for WorkProductId {
|
||||
impl StableOrd for WorkProductId {
|
||||
// Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// `WorkProductId` sort order is not affected by (de)serialization.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
// Some types are used a lot. Make sure they don't unintentionally get bigger.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, Modul
|
|||
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError};
|
||||
use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError};
|
||||
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
|
||||
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
|
||||
use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
|
||||
use rustc_attr as attr;
|
||||
|
|
@ -1313,7 +1313,17 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
_ => {
|
||||
let orig_macro_rules_scope = self.parent_scope.macro_rules;
|
||||
self.build_reduced_graph_for_item(item);
|
||||
visit::walk_item(self, item);
|
||||
match item.kind {
|
||||
ItemKind::Mod(..) => {
|
||||
// Visit attributes after items for backward compatibility.
|
||||
// This way they can use `macro_rules` defined later.
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
item.kind.walk(item, AssocCtxt::Trait, self);
|
||||
visit::walk_list!(self, visit_attribute, &item.attrs);
|
||||
}
|
||||
_ => visit::walk_item(self, item),
|
||||
}
|
||||
match item.kind {
|
||||
ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
|
||||
self.parent_scope.macro_rules
|
||||
|
|
@ -1514,7 +1524,10 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
if krate.is_placeholder {
|
||||
self.visit_invoc_in_module(krate.id);
|
||||
} else {
|
||||
visit::walk_crate(self, krate);
|
||||
// Visit attributes after items for backward compatibility.
|
||||
// This way they can use `macro_rules` defined later.
|
||||
visit::walk_list!(self, visit_item, &krate.items);
|
||||
visit::walk_list!(self, visit_attribute, &krate.attrs);
|
||||
self.contains_macro_use(&krate.attrs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::errors::CannotDetermineMacroResolution;
|
|||
use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope};
|
||||
use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive};
|
||||
use crate::Namespace::*;
|
||||
use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, Used};
|
||||
use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, NameBindingKind, Used};
|
||||
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
|
||||
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
|
||||
use rustc_ast::expand::StrippedCfgItem;
|
||||
|
|
@ -18,15 +18,18 @@ use rustc_errors::{Applicability, StashKey};
|
|||
use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand};
|
||||
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use rustc_expand::compile_declarative_macro;
|
||||
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
|
||||
use rustc_expand::expand::{
|
||||
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
|
||||
};
|
||||
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::RegisteredTools;
|
||||
use rustc_middle::ty::{TyCtxt, Visibility};
|
||||
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
||||
use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
|
||||
use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
|
||||
use rustc_session::lint::builtin::{
|
||||
LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, SOFT_UNSTABLE,
|
||||
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACROS, UNUSED_MACRO_RULES,
|
||||
};
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::edit_distance::edit_distance;
|
||||
|
|
@ -140,9 +143,10 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
|
|||
}
|
||||
}
|
||||
}
|
||||
// We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools,
|
||||
// but it's not an error to register them explicitly.
|
||||
let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri];
|
||||
// We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known
|
||||
// tools, but it's not an error to register them explicitly.
|
||||
let predefined_tools =
|
||||
[sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri, sym::rust_analyzer];
|
||||
registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span));
|
||||
registered_tools
|
||||
}
|
||||
|
|
@ -288,6 +292,16 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
|
|||
let parent_scope = &ParentScope { derives, ..parent_scope };
|
||||
let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
|
||||
let node_id = invoc.expansion_data.lint_node_id;
|
||||
// This is a heuristic, but it's good enough for the lint.
|
||||
let looks_like_invoc_in_mod_inert_attr = self
|
||||
.invocation_parents
|
||||
.get(&invoc_id)
|
||||
.or_else(|| self.invocation_parents.get(&eager_expansion_root))
|
||||
.map(|&(mod_def_id, _)| mod_def_id)
|
||||
.filter(|&mod_def_id| {
|
||||
invoc.fragment_kind == AstFragmentKind::Expr
|
||||
&& self.tcx.def_kind(mod_def_id) == DefKind::Mod
|
||||
});
|
||||
let (ext, res) = self.smart_resolve_macro_path(
|
||||
path,
|
||||
kind,
|
||||
|
|
@ -298,6 +312,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
|
|||
force,
|
||||
soft_custom_inner_attributes_gate(path, invoc),
|
||||
deleg_impl,
|
||||
looks_like_invoc_in_mod_inert_attr,
|
||||
)?;
|
||||
|
||||
let span = invoc.span();
|
||||
|
|
@ -520,6 +535,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
force: bool,
|
||||
soft_custom_inner_attributes_gate: bool,
|
||||
deleg_impl: Option<LocalDefId>,
|
||||
invoc_in_mod_inert_attr: Option<LocalDefId>,
|
||||
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
|
||||
let (ext, res) = match self.resolve_macro_or_delegation_path(
|
||||
path,
|
||||
|
|
@ -528,6 +544,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
true,
|
||||
force,
|
||||
deleg_impl,
|
||||
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
|
||||
) {
|
||||
Ok((Some(ext), res)) => (ext, res),
|
||||
Ok((None, res)) => (self.dummy_ext(kind), res),
|
||||
|
|
@ -682,20 +699,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
trace: bool,
|
||||
force: bool,
|
||||
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
||||
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None)
|
||||
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None)
|
||||
}
|
||||
|
||||
fn resolve_macro_or_delegation_path(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
ast_path: &ast::Path,
|
||||
kind: Option<MacroKind>,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
trace: bool,
|
||||
force: bool,
|
||||
deleg_impl: Option<LocalDefId>,
|
||||
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
||||
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
|
||||
let path_span = path.span;
|
||||
let mut path = Segment::from_path(path);
|
||||
let path_span = ast_path.span;
|
||||
let mut path = Segment::from_path(ast_path);
|
||||
|
||||
// Possibly apply the macro helper hack
|
||||
if deleg_impl.is_none()
|
||||
|
|
@ -761,6 +779,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
|
||||
let res = binding.map(|binding| binding.res());
|
||||
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
|
||||
self.report_out_of_scope_macro_calls(
|
||||
ast_path,
|
||||
parent_scope,
|
||||
invoc_in_mod_inert_attr,
|
||||
binding.ok(),
|
||||
);
|
||||
res
|
||||
};
|
||||
|
||||
|
|
@ -1013,6 +1037,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn report_out_of_scope_macro_calls(
|
||||
&mut self,
|
||||
path: &ast::Path,
|
||||
parent_scope: &ParentScope<'a>,
|
||||
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
||||
binding: Option<NameBinding<'a>>,
|
||||
) {
|
||||
if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr
|
||||
&& let Some(binding) = binding
|
||||
// This is a `macro_rules` itself, not some import.
|
||||
&& let NameBindingKind::Res(res) = binding.kind
|
||||
&& let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res
|
||||
// And the `macro_rules` is defined inside the attribute's module,
|
||||
// so it cannot be in scope unless imported.
|
||||
&& self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id())
|
||||
{
|
||||
// Try to resolve our ident ignoring `macro_rules` scopes.
|
||||
// If such resolution is successful and gives the same result
|
||||
// (e.g. if the macro is re-imported), then silence the lint.
|
||||
let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
|
||||
let fallback_binding = self.early_resolve_ident_in_lexical_scope(
|
||||
path.segments[0].ident,
|
||||
ScopeSet::Macro(MacroKind::Bang),
|
||||
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
|
||||
self.tcx.sess.psess.buffer_lint(
|
||||
OUT_OF_SCOPE_MACRO_CALLS,
|
||||
path.span,
|
||||
node_id,
|
||||
BuiltinLintDiag::OutOfScopeMacroCalls { path: pprust::path_to_string(path) },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
|
||||
// Reserve some names that are not quite covered by the general check
|
||||
// performed on `Resolver::builtin_attrs`.
|
||||
|
|
|
|||
|
|
@ -232,7 +232,8 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
|
|||
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||
.map(move |assoc_ty| {
|
||||
super_poly_trait_ref.map_bound(|super_trait_ref| {
|
||||
let alias_ty = ty::AliasTy::new(tcx, assoc_ty.def_id, super_trait_ref.args);
|
||||
let alias_ty =
|
||||
ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args);
|
||||
let resolved = tcx.normalize_erasing_regions(
|
||||
ty::ParamEnv::reveal_all(),
|
||||
alias_ty.to_ty(tcx),
|
||||
|
|
@ -351,7 +352,7 @@ pub fn transform_instance<'tcx>(
|
|||
// Adjust the type ids of VTableShims to the type id expected in the call sites for the
|
||||
// entry in the vtable (i.e., by using the signature of the closure passed as an argument
|
||||
// to the shim, or by just removing self).
|
||||
let trait_ref = ty::TraitRef::new(tcx, trait_id, instance.args);
|
||||
let trait_ref = ty::TraitRef::new_from_args(tcx, trait_id, instance.args);
|
||||
let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
|
||||
instance.args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
|
||||
}
|
||||
|
|
@ -432,7 +433,7 @@ pub fn transform_instance<'tcx>(
|
|||
x => bug!("Unexpected type kind for closure-like: {x:?}"),
|
||||
};
|
||||
let concrete_args = tcx.mk_args_trait(closure_ty, inputs.map(Into::into));
|
||||
let trait_ref = ty::TraitRef::new(tcx, trait_id, concrete_args);
|
||||
let trait_ref = ty::TraitRef::new_from_args(tcx, trait_id, concrete_args);
|
||||
let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
|
||||
let abstract_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
|
||||
// There should be exactly one method on this trait, and it should be the one we're
|
||||
|
|
|
|||
|
|
@ -498,9 +498,11 @@ pub enum OutputType {
|
|||
DepInfo,
|
||||
}
|
||||
|
||||
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
|
||||
unsafe impl StableOrd for OutputType {
|
||||
impl StableOrd for OutputType {
|
||||
const CAN_USE_UNSTABLE_SORT: bool = true;
|
||||
|
||||
// Trivial C-Style enums have a stable sort order across compilation sessions.
|
||||
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
|
||||
}
|
||||
|
||||
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
|
||||
|
|
|
|||
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