Auto merge of #3428 - rust-lang:rustup-2024-03-30, r=RalfJung
Automatic Rustup
This commit is contained in:
commit
d3accba79b
@ -702,19 +702,10 @@ pub struct PatField {
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum ByRef {
|
||||
Yes,
|
||||
Yes(Mutability),
|
||||
No,
|
||||
}
|
||||
|
||||
impl From<bool> for ByRef {
|
||||
fn from(b: bool) -> ByRef {
|
||||
match b {
|
||||
false => ByRef::No,
|
||||
true => ByRef::Yes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explicit binding annotations given in the HIR for a binding. Note
|
||||
/// that this is not the final binding *mode* that we infer after type
|
||||
/// inference.
|
||||
@ -724,9 +715,11 @@ pub struct BindingAnnotation(pub ByRef, pub Mutability);
|
||||
|
||||
impl BindingAnnotation {
|
||||
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
|
||||
pub const REF: Self = Self(ByRef::Yes, Mutability::Not);
|
||||
pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not);
|
||||
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
|
||||
pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut);
|
||||
pub const REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Not);
|
||||
pub const MUT_REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Mut);
|
||||
pub const MUT_REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Mut);
|
||||
|
||||
pub fn prefix_str(self) -> &'static str {
|
||||
match self {
|
||||
@ -734,6 +727,8 @@ impl BindingAnnotation {
|
||||
Self::REF => "ref ",
|
||||
Self::MUT => "mut ",
|
||||
Self::REF_MUT => "ref mut ",
|
||||
Self::MUT_REF => "mut ref ",
|
||||
Self::MUT_REF_MUT => "mut ref mut ",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1847,8 +1847,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// the case where we have a mutable pattern to a reference as that would
|
||||
// no longer be an `ImplicitSelf`.
|
||||
TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl {
|
||||
hir::Mutability::Not => hir::ImplicitSelfKind::ImmRef,
|
||||
hir::Mutability::Mut => hir::ImplicitSelfKind::MutRef,
|
||||
hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,
|
||||
hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,
|
||||
},
|
||||
_ => hir::ImplicitSelfKind::None,
|
||||
}
|
||||
|
@ -1552,7 +1552,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
|
||||
/// like it's setting an associated type, provide an appropriate suggestion.
|
||||
fn deny_equality_constraints(
|
||||
this: &mut AstValidator<'_>,
|
||||
this: &AstValidator<'_>,
|
||||
predicate: &WhereEqPredicate,
|
||||
generics: &Generics,
|
||||
) {
|
||||
|
@ -565,6 +565,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
@ -1545,12 +1545,15 @@ impl<'a> State<'a> {
|
||||
PatKind::Wild => self.word("_"),
|
||||
PatKind::Never => self.word("!"),
|
||||
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => {
|
||||
if *by_ref == ByRef::Yes {
|
||||
self.word_nbsp("ref");
|
||||
}
|
||||
if mutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
if let ByRef::Yes(rmutbl) = by_ref {
|
||||
self.word_nbsp("ref");
|
||||
if rmutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
}
|
||||
self.print_ident(*ident);
|
||||
if let Some(p) = sub {
|
||||
self.space();
|
||||
|
@ -337,7 +337,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn suggest_ref_or_clone(
|
||||
&mut self,
|
||||
&self,
|
||||
mpi: MovePathIndex,
|
||||
move_span: Span,
|
||||
err: &mut Diag<'tcx>,
|
||||
@ -1125,7 +1125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn report_use_while_mutably_borrowed(
|
||||
&mut self,
|
||||
&self,
|
||||
location: Location,
|
||||
(place, _span): (Place<'tcx>, Span),
|
||||
borrow: &BorrowData<'tcx>,
|
||||
@ -1174,7 +1174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn report_conflicting_borrow(
|
||||
&mut self,
|
||||
&self,
|
||||
location: Location,
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
@ -2463,7 +2463,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn report_local_value_does_not_live_long_enough(
|
||||
&mut self,
|
||||
&self,
|
||||
location: Location,
|
||||
name: &str,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
@ -2642,7 +2642,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn report_thread_local_value_does_not_live_long_enough(
|
||||
&mut self,
|
||||
&self,
|
||||
drop_span: Span,
|
||||
borrow_span: Span,
|
||||
) -> Diag<'tcx> {
|
||||
@ -2663,7 +2663,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_temporary_value_does_not_live_long_enough(
|
||||
&mut self,
|
||||
&self,
|
||||
location: Location,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
drop_span: Span,
|
||||
@ -2921,7 +2921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn report_escaping_closure_capture(
|
||||
&mut self,
|
||||
&self,
|
||||
use_span: UseSpans<'tcx>,
|
||||
var_span: Span,
|
||||
fr_name: &RegionName,
|
||||
@ -3031,7 +3031,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn report_escaping_data(
|
||||
&mut self,
|
||||
&self,
|
||||
borrow_span: Span,
|
||||
name: &Option<String>,
|
||||
upvar_span: Span,
|
||||
@ -3065,7 +3065,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_moved_indexes(
|
||||
&mut self,
|
||||
&self,
|
||||
location: Location,
|
||||
mpi: MovePathIndex,
|
||||
) -> (Vec<MoveSite>, Vec<Location>) {
|
||||
@ -3854,7 +3854,7 @@ 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: &mut 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(
|
||||
|
@ -4,9 +4,8 @@
|
||||
use core::ops::ControlFlow;
|
||||
use hir::{ExprKind, Param};
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node};
|
||||
use rustc_infer::traits;
|
||||
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt};
|
||||
@ -304,7 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
{
|
||||
match *decl.local_info() {
|
||||
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
|
||||
opt_ty_info: Some(sp),
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
@ -342,7 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
} else if decl.mutability.is_not() {
|
||||
if matches!(
|
||||
decl.local_info(),
|
||||
LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
|
||||
LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::RefMut))
|
||||
) {
|
||||
err.note(
|
||||
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
||||
@ -407,7 +406,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
if let Some(fn_decl) = node.fn_decl() {
|
||||
if !matches!(
|
||||
fn_decl.implicit_self,
|
||||
hir::ImplicitSelfKind::ImmRef | hir::ImplicitSelfKind::MutRef
|
||||
hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut
|
||||
) {
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
@ -717,7 +716,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
debug!("local_decl: {:?}", local_decl);
|
||||
let pat_span = match *local_decl.local_info() {
|
||||
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span,
|
||||
@ -1070,7 +1069,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
binding_mode: BindingAnnotation(ByRef::No, _),
|
||||
opt_ty_info,
|
||||
..
|
||||
})) => {
|
||||
@ -1138,7 +1137,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
binding_mode: BindingAnnotation(ByRef::Yes(_), _),
|
||||
..
|
||||
})) => {
|
||||
let pattern_span: Span = local_decl.source_info.span;
|
||||
@ -1329,7 +1328,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
|
||||
match *local_decl.local_info() {
|
||||
// Check if mutably borrowing a mutable reference.
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
|
||||
..
|
||||
})) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||
LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {
|
||||
@ -1338,7 +1337,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
|
||||
//
|
||||
// Deliberately fall into this case for all implicit self types,
|
||||
// so that we don't fall into the next case with them.
|
||||
kind == hir::ImplicitSelfKind::MutRef
|
||||
kind == hir::ImplicitSelfKind::RefMut
|
||||
}
|
||||
_ if Some(kw::SelfLower) == local_name => {
|
||||
// Otherwise, check if the name is the `self` keyword - in which case
|
||||
|
@ -87,6 +87,8 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
move_data: &MoveData<'tcx>,
|
||||
//FIXME: this is not mutated, but expected to be modified as
|
||||
// out param, bug?
|
||||
dropped_at: &mut Vec<(Local, Location)>,
|
||||
) {
|
||||
debug!("populate_access_facts()");
|
||||
|
@ -200,7 +200,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
for local in boring_locals {
|
||||
let local_ty = self.cx.body.local_decls[local].ty;
|
||||
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
|
||||
let typeck = &mut self.cx.typeck;
|
||||
let typeck = &self.cx.typeck;
|
||||
move || LivenessContext::compute_drop_data(typeck, local_ty)
|
||||
});
|
||||
|
||||
@ -542,7 +542,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
);
|
||||
|
||||
let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
|
||||
let typeck = &mut self.typeck;
|
||||
let typeck = &self.typeck;
|
||||
move || Self::compute_drop_data(typeck, dropped_ty)
|
||||
});
|
||||
|
||||
@ -597,10 +597,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||
});
|
||||
}
|
||||
|
||||
fn compute_drop_data(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
dropped_ty: Ty<'tcx>,
|
||||
) -> DropData<'tcx> {
|
||||
fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
|
||||
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
|
||||
|
||||
match typeck
|
||||
|
@ -29,7 +29,7 @@ pub struct AsmArgs {
|
||||
}
|
||||
|
||||
fn parse_args<'a>(
|
||||
ecx: &mut ExtCtxt<'a>,
|
||||
ecx: &ExtCtxt<'a>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
is_global_asm: bool,
|
||||
@ -303,7 +303,7 @@ pub fn parse_asm_args<'a>(
|
||||
///
|
||||
/// This function must be called immediately after the option token is parsed.
|
||||
/// Otherwise, the suggestion will be incorrect.
|
||||
fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
|
||||
fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
|
||||
// Tool-only output
|
||||
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
|
||||
p.psess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
|
||||
@ -315,7 +315,7 @@ fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
|
||||
/// This function must be called immediately after the option token is parsed.
|
||||
/// Otherwise, the error will not point to the correct spot.
|
||||
fn try_set_option<'a>(
|
||||
p: &mut Parser<'a>,
|
||||
p: &Parser<'a>,
|
||||
args: &mut AsmArgs,
|
||||
symbol: Symbol,
|
||||
option: ast::InlineAsmOptions,
|
||||
|
@ -111,7 +111,7 @@ fn expr_if_not(
|
||||
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
|
||||
}
|
||||
|
||||
fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
|
||||
fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
|
||||
let mut parser = cx.new_parser_from_tts(stream);
|
||||
|
||||
if parser.token == token::Eof {
|
||||
|
@ -35,7 +35,7 @@ pub fn expand_cfg(
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
|
||||
fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
|
||||
if p.token == token::Eof {
|
||||
|
@ -10,7 +10,7 @@ use rustc_span::Span;
|
||||
|
||||
pub(crate) struct Expander;
|
||||
|
||||
fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
|
||||
fn validate_input<'a>(ecx: &ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
|
||||
use errors::CfgAccessibleInvalid::*;
|
||||
match mi.meta_item_list() {
|
||||
None => {}
|
||||
|
@ -8,7 +8,7 @@ use crate::errors;
|
||||
|
||||
/// Emits errors for literal expressions that are invalid inside and outside of an array.
|
||||
fn invalid_type_err(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
token_lit: token::Lit,
|
||||
span: Span,
|
||||
is_nested: bool,
|
||||
@ -65,7 +65,7 @@ fn invalid_type_err(
|
||||
/// Otherwise, returns `None`, and either pushes the `expr`'s span to `missing_literals` or
|
||||
/// updates `guar` accordingly.
|
||||
fn handle_array_element(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
guar: &mut Option<ErrorGuaranteed>,
|
||||
missing_literals: &mut Vec<rustc_span::Span>,
|
||||
expr: &P<rustc_ast::Expr>,
|
||||
|
@ -6,7 +6,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub fn expand_deriving_copy(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -29,7 +29,7 @@ pub fn expand_deriving_copy(
|
||||
}
|
||||
|
||||
pub fn expand_deriving_const_param_ty(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
|
@ -9,7 +9,7 @@ use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_clone(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -94,7 +94,7 @@ pub fn expand_deriving_clone(
|
||||
|
||||
fn cs_clone_simple(
|
||||
name: &str,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
is_union: bool,
|
||||
@ -157,14 +157,14 @@ fn cs_clone_simple(
|
||||
|
||||
fn cs_clone(
|
||||
name: &str,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
) -> BlockOrExpr {
|
||||
let ctor_path;
|
||||
let all_fields;
|
||||
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
|
||||
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo| {
|
||||
let subcall = |cx: &ExtCtxt<'_>, field: &FieldInfo| {
|
||||
let args = thin_vec![field.self_expr.clone()];
|
||||
cx.expr_call_global(field.span, fn_path.clone(), args)
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_eq(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -49,7 +49,7 @@ pub fn expand_deriving_eq(
|
||||
}
|
||||
|
||||
fn cs_total_eq_assert(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
) -> BlockOrExpr {
|
||||
|
@ -8,7 +8,7 @@ use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_ord(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -39,7 +39,7 @@ pub fn expand_deriving_ord(
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
pub fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
let test_id = Ident::new(sym::cmp, span);
|
||||
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
||||
let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
|
||||
|
@ -9,14 +9,14 @@ use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_partial_eq(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
fn cs_eq(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
let base = true;
|
||||
let expr = cs_fold(
|
||||
true, // use foldl
|
||||
|
@ -8,7 +8,7 @@ use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_partial_ord(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -69,7 +69,7 @@ pub fn expand_deriving_partial_ord(
|
||||
}
|
||||
|
||||
fn cs_partial_cmp(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
tag_then_data: bool,
|
||||
|
@ -9,7 +9,7 @@ use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_debug(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -45,7 +45,7 @@ pub fn expand_deriving_debug(
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
// We want to make sure we have the ctxt set so that we can use unstable methods
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
|
||||
@ -209,7 +209,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||
/// }
|
||||
/// ```
|
||||
fn show_fieldless_enum(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
def: &EnumDef,
|
||||
substr: &Substructure<'_>,
|
||||
|
@ -11,7 +11,7 @@ use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_rustc_decodable(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -63,7 +63,7 @@ pub fn expand_deriving_rustc_decodable(
|
||||
}
|
||||
|
||||
fn decodable_substructure(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
krate: Symbol,
|
||||
@ -186,14 +186,14 @@ fn decodable_substructure(
|
||||
/// - `outer_pat_path` is the path to this enum variant/struct
|
||||
/// - `getarg` should retrieve the `usize`-th field with name `@str`.
|
||||
fn decode_static_fields<F>(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
outer_pat_path: ast::Path,
|
||||
fields: &StaticFields,
|
||||
mut getarg: F,
|
||||
) -> P<Expr>
|
||||
where
|
||||
F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
|
||||
F: FnMut(&ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
|
||||
{
|
||||
match fields {
|
||||
Unnamed(fields, is_tuple) => {
|
||||
|
@ -13,7 +13,7 @@ use smallvec::SmallVec;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_default(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -54,7 +54,7 @@ pub fn expand_deriving_default(
|
||||
}
|
||||
|
||||
fn default_struct_substructure(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
summary: &StaticFields,
|
||||
@ -81,7 +81,7 @@ fn default_struct_substructure(
|
||||
}
|
||||
|
||||
fn default_enum_substructure(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
enum_def: &EnumDef,
|
||||
) -> BlockOrExpr {
|
||||
@ -103,7 +103,7 @@ fn default_enum_substructure(
|
||||
}
|
||||
|
||||
fn extract_default_variant<'a>(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
enum_def: &'a EnumDef,
|
||||
trait_span: Span,
|
||||
) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
|
||||
@ -173,7 +173,7 @@ fn extract_default_variant<'a>(
|
||||
}
|
||||
|
||||
fn validate_default_attribute(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
default_variant: &rustc_ast::Variant,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let attrs: SmallVec<[_; 1]> =
|
||||
|
@ -95,7 +95,7 @@ use rustc_span::Span;
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
|
||||
pub fn expand_deriving_rustc_encodable(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -147,7 +147,7 @@ pub fn expand_deriving_rustc_encodable(
|
||||
}
|
||||
|
||||
fn encodable_substructure(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
krate: Symbol,
|
||||
|
@ -330,7 +330,7 @@ pub enum SubstructureFields<'a> {
|
||||
/// Combine the values of all the fields together. The last argument is
|
||||
/// all the fields of all the structures.
|
||||
pub type CombineSubstructureFunc<'a> =
|
||||
Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> BlockOrExpr + 'a>;
|
||||
Box<dyn FnMut(&ExtCtxt<'_>, Span, &Substructure<'_>) -> BlockOrExpr + 'a>;
|
||||
|
||||
pub fn combine_substructure(
|
||||
f: CombineSubstructureFunc<'_>,
|
||||
@ -454,7 +454,7 @@ fn find_type_parameters(
|
||||
impl<'a> TraitDef<'a> {
|
||||
pub fn expand(
|
||||
self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &'a Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
@ -464,7 +464,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
pub fn expand_ext(
|
||||
self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &'a Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
@ -577,7 +577,7 @@ impl<'a> TraitDef<'a> {
|
||||
/// therefore does not get bound by the derived trait.
|
||||
fn create_derived_impl(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
field_tys: Vec<P<ast::Ty>>,
|
||||
@ -802,7 +802,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
fn expand_struct_def(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
struct_def: &'a VariantData,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
@ -856,7 +856,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
fn expand_enum_def(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
enum_def: &'a EnumDef,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
@ -914,7 +914,7 @@ impl<'a> TraitDef<'a> {
|
||||
impl<'a> MethodDef<'a> {
|
||||
fn call_substructure_method(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
nonselflike_args: &[P<Expr>],
|
||||
@ -929,7 +929,7 @@ impl<'a> MethodDef<'a> {
|
||||
|
||||
fn get_ret_ty(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
generics: &Generics,
|
||||
type_ident: Ident,
|
||||
@ -950,7 +950,7 @@ impl<'a> MethodDef<'a> {
|
||||
// `&self`.
|
||||
fn extract_arg_details(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
@ -986,7 +986,7 @@ impl<'a> MethodDef<'a> {
|
||||
|
||||
fn create_method(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
generics: &Generics,
|
||||
@ -1077,7 +1077,7 @@ impl<'a> MethodDef<'a> {
|
||||
/// ```
|
||||
fn expand_struct_method_body<'b>(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'b>,
|
||||
struct_def: &'b VariantData,
|
||||
type_ident: Ident,
|
||||
@ -1100,7 +1100,7 @@ impl<'a> MethodDef<'a> {
|
||||
|
||||
fn expand_static_struct_method_body(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
struct_def: &VariantData,
|
||||
type_ident: Ident,
|
||||
@ -1154,7 +1154,7 @@ impl<'a> MethodDef<'a> {
|
||||
/// `Unify`), and possibly a default arm.
|
||||
fn expand_enum_method_body<'b>(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'b>,
|
||||
enum_def: &'b EnumDef,
|
||||
type_ident: Ident,
|
||||
@ -1403,7 +1403,7 @@ impl<'a> MethodDef<'a> {
|
||||
|
||||
fn expand_static_enum_method_body(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
enum_def: &EnumDef,
|
||||
type_ident: Ident,
|
||||
@ -1430,7 +1430,7 @@ impl<'a> MethodDef<'a> {
|
||||
|
||||
// general helper methods.
|
||||
impl<'a> TraitDef<'a> {
|
||||
fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
|
||||
fn summarise_struct(&self, cx: &ExtCtxt<'_>, struct_def: &VariantData) -> StaticFields {
|
||||
let mut named_idents = Vec::new();
|
||||
let mut just_spans = Vec::new();
|
||||
for field in struct_def.fields() {
|
||||
@ -1460,7 +1460,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
fn create_struct_patterns(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
struct_path: ast::Path,
|
||||
struct_def: &'a VariantData,
|
||||
prefixes: &[String],
|
||||
@ -1553,7 +1553,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
fn create_struct_pattern_fields(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
struct_def: &'a VariantData,
|
||||
prefixes: &[String],
|
||||
) -> Vec<FieldInfo> {
|
||||
@ -1570,7 +1570,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
fn create_struct_field_access_fields(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
selflike_args: &[P<Expr>],
|
||||
struct_def: &'a VariantData,
|
||||
is_packed: bool,
|
||||
@ -1668,13 +1668,13 @@ pub enum CsFold<'a> {
|
||||
/// Statics may not be folded over.
|
||||
pub fn cs_fold<F>(
|
||||
use_foldl: bool,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure<'_>,
|
||||
mut f: F,
|
||||
) -> P<Expr>
|
||||
where
|
||||
F: FnMut(&mut ExtCtxt<'_>, CsFold<'_>) -> P<Expr>,
|
||||
F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> P<Expr>,
|
||||
{
|
||||
match substructure.fields {
|
||||
EnumMatching(.., all_fields) | Struct(_, all_fields) => {
|
||||
|
@ -8,7 +8,7 @@ use rustc_span::Span;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
pub fn expand_deriving_hash(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
@ -46,11 +46,7 @@ pub fn expand_deriving_hash(
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
}
|
||||
|
||||
fn hash_substructure(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substr: &Substructure<'_>,
|
||||
) -> BlockOrExpr {
|
||||
fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||
let [state_expr] = substr.nonselflike_args else {
|
||||
cx.dcx().span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`");
|
||||
};
|
||||
|
@ -40,7 +40,7 @@ pub mod partial_ord;
|
||||
pub mod generic;
|
||||
|
||||
pub(crate) type BuiltinDeriveFn =
|
||||
fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
|
||||
fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
|
||||
|
||||
pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
|
||||
|
||||
@ -117,7 +117,7 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
|
||||
}
|
||||
|
||||
fn assert_ty_bounds(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
stmts: &mut ThinVec<ast::Stmt>,
|
||||
ty: P<ast::Ty>,
|
||||
span: Span,
|
||||
|
@ -40,7 +40,7 @@ pub fn expand_unreachable<'cx>(
|
||||
|
||||
fn expand<'cx>(
|
||||
mac: rustc_span::Symbol,
|
||||
cx: &'cx mut ExtCtxt<'_>,
|
||||
cx: &'cx ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> MacroExpanderResult<'cx> {
|
||||
|
@ -65,7 +65,7 @@ struct MacroInput {
|
||||
/// ```text
|
||||
/// Ok((fmtstr, parsed arguments))
|
||||
/// ```
|
||||
fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> {
|
||||
fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> {
|
||||
let mut args = FormatArguments::new();
|
||||
|
||||
let mut p = ecx.new_parser_from_tts(tts);
|
||||
@ -604,7 +604,7 @@ fn invalid_placeholder_type_error(
|
||||
}
|
||||
|
||||
fn report_missing_placeholders(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
ecx: &ExtCtxt<'_>,
|
||||
unused: Vec<(Span, bool)>,
|
||||
used: &[bool],
|
||||
args: &FormatArguments,
|
||||
@ -734,7 +734,7 @@ fn report_missing_placeholders(
|
||||
/// This function detects and reports unused format!() arguments that are
|
||||
/// redundant due to implicit captures (e.g. `format!("{x}", x)`).
|
||||
fn report_redundant_format_arguments<'a>(
|
||||
ecx: &mut ExtCtxt<'a>,
|
||||
ecx: &ExtCtxt<'a>,
|
||||
args: &FormatArguments,
|
||||
used: &[bool],
|
||||
placeholders: Vec<(Span, &str)>,
|
||||
@ -806,7 +806,7 @@ fn report_redundant_format_arguments<'a>(
|
||||
/// there are named arguments or numbered positional arguments in the
|
||||
/// format string.
|
||||
fn report_invalid_references(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
ecx: &ExtCtxt<'_>,
|
||||
invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
|
||||
template: &[FormatArgsPiece],
|
||||
fmt_span: Span,
|
||||
|
@ -234,7 +234,7 @@ pub fn expand_include_bytes(
|
||||
}
|
||||
|
||||
fn load_binary_file(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
original_path: &Path,
|
||||
macro_span: Span,
|
||||
path_span: Span,
|
||||
|
@ -96,7 +96,7 @@ pub fn expand_bench(
|
||||
}
|
||||
|
||||
pub fn expand_test_or_bench(
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
cx: &ExtCtxt<'_>,
|
||||
attr_sp: Span,
|
||||
item: Annotatable,
|
||||
is_bench: bool,
|
||||
|
@ -89,11 +89,7 @@ impl DebugContext {
|
||||
match &source_file.name {
|
||||
FileName::Real(path) => {
|
||||
let (dir_path, file_name) =
|
||||
split_path_dir_and_file(if self.should_remap_filepaths {
|
||||
path.remapped_path_if_available()
|
||||
} else {
|
||||
path.local_path_if_available()
|
||||
});
|
||||
split_path_dir_and_file(path.to_path(self.filename_display_preference));
|
||||
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
|
||||
let file_name = osstr_as_utf8_bytes(file_name);
|
||||
|
||||
@ -115,14 +111,7 @@ impl DebugContext {
|
||||
filename => {
|
||||
let dir_id = line_program.default_directory();
|
||||
let dummy_file_name = LineString::new(
|
||||
filename
|
||||
.display(if self.should_remap_filepaths {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
})
|
||||
.to_string()
|
||||
.into_bytes(),
|
||||
filename.display(self.filename_display_preference).to_string().into_bytes(),
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
|
@ -42,7 +42,7 @@ pub(crate) struct DebugContext {
|
||||
namespace_map: DefIdMap<UnitEntryId>,
|
||||
array_size_type: UnitEntryId,
|
||||
|
||||
should_remap_filepaths: bool,
|
||||
filename_display_preference: FileNameDisplayPreference,
|
||||
}
|
||||
|
||||
pub(crate) struct FunctionDebugContext {
|
||||
@ -84,22 +84,18 @@ impl DebugContext {
|
||||
|
||||
let mut dwarf = DwarfUnit::new(encoding);
|
||||
|
||||
let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen();
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
|
||||
let filename_display_preference =
|
||||
tcx.sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
let producer = producer(tcx.sess);
|
||||
let comp_dir = tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.to_string_lossy(if should_remap_filepaths {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
})
|
||||
.into_owned();
|
||||
let comp_dir =
|
||||
tcx.sess.opts.working_dir.to_string_lossy(filename_display_preference).to_string();
|
||||
|
||||
let (name, file_info) = match tcx.sess.local_crate_source_file() {
|
||||
Some(path) => {
|
||||
let name = path.to_string_lossy().into_owned();
|
||||
let name = path.to_string_lossy(filename_display_preference).to_string();
|
||||
(name, None)
|
||||
}
|
||||
None => (tcx.crate_name(LOCAL_CRATE).to_string(), None),
|
||||
@ -156,7 +152,7 @@ impl DebugContext {
|
||||
stack_pointer_register,
|
||||
namespace_map: DefIdMap::default(),
|
||||
array_size_type,
|
||||
should_remap_filepaths,
|
||||
filename_display_preference,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,8 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_errors::{DiagCtxt, FatalError, Level};
|
||||
use rustc_fs_util::{link_or_copy, path_to_c_string};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes};
|
||||
use rustc_session::config::{RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::InnerSpan;
|
||||
@ -257,18 +258,17 @@ pub fn target_machine_factory(
|
||||
};
|
||||
let debuginfo_compression = SmallCStr::new(&debuginfo_compression);
|
||||
|
||||
let should_prefer_remapped_for_split_debuginfo_paths =
|
||||
sess.should_prefer_remapped_for_split_debuginfo_paths();
|
||||
let file_name_display_preference =
|
||||
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
|
||||
let path = path.unwrap_or_default();
|
||||
let path = if should_prefer_remapped_for_split_debuginfo_paths {
|
||||
path_mapping.map_prefix(path).0
|
||||
} else {
|
||||
path.into()
|
||||
};
|
||||
CString::new(path.to_str().unwrap()).unwrap()
|
||||
let path = path_mapping
|
||||
.to_real_filename(path)
|
||||
.to_string_lossy(file_name_display_preference)
|
||||
.into_owned();
|
||||
CString::new(path).unwrap()
|
||||
};
|
||||
|
||||
let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file);
|
||||
|
@ -173,8 +173,14 @@ impl GlobalFileTable {
|
||||
// Since rustc generates coverage maps with relative paths, the
|
||||
// compilation directory can be combined with the relative paths
|
||||
// to get absolute paths, if needed.
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let working_dir: &str = &tcx.sess.opts.working_dir.for_codegen(tcx.sess).to_string_lossy();
|
||||
let working_dir: &str = &tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
|
||||
.to_string_lossy();
|
||||
|
||||
llvm::build_byte_buffer(|buffer| {
|
||||
coverageinfo::write_filenames_section_to_buffer(
|
||||
|
@ -554,13 +554,16 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) ->
|
||||
) -> &'ll DIFile {
|
||||
debug!(?source_file.name);
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let filename_display_preference =
|
||||
cx.sess().filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
let (directory, file_name) = match &source_file.name {
|
||||
FileName::Real(filename) => {
|
||||
let working_directory = &cx.sess().opts.working_dir;
|
||||
debug!(?working_directory);
|
||||
|
||||
if cx.sess().should_prefer_remapped_for_codegen() {
|
||||
if filename_display_preference == FileNameDisplayPreference::Remapped {
|
||||
let filename = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
@ -623,7 +626,7 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) ->
|
||||
}
|
||||
other => {
|
||||
debug!(?other);
|
||||
("".into(), other.for_codegen(cx.sess()).to_string_lossy().into_owned())
|
||||
("".into(), other.display(filename_display_preference).to_string())
|
||||
}
|
||||
};
|
||||
|
||||
@ -832,9 +835,11 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
codegen_unit_name: &str,
|
||||
debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
|
||||
) -> &'ll DIDescriptor {
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
let mut name_in_debuginfo = tcx
|
||||
.sess
|
||||
.local_crate_source_file()
|
||||
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_path_buf())
|
||||
.unwrap_or_else(|| PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()));
|
||||
|
||||
// To avoid breaking split DWARF, we need to ensure that each codegen unit
|
||||
@ -862,30 +867,29 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
// FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
|
||||
let producer = format!("clang LLVM ({rustc_producer})");
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||
let work_dir = tcx.sess.opts.working_dir.for_codegen(tcx.sess).to_string_lossy();
|
||||
let work_dir = tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO)
|
||||
.to_string_lossy();
|
||||
let output_filenames = tcx.output_filenames(());
|
||||
let split_name = if tcx.sess.target_can_use_split_dwarf() {
|
||||
output_filenames
|
||||
.split_dwarf_path(
|
||||
tcx.sess.split_debuginfo(),
|
||||
tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
Some(codegen_unit_name),
|
||||
)
|
||||
// We get a path relative to the working directory from split_dwarf_path
|
||||
.map(|f| {
|
||||
if tcx.sess.should_prefer_remapped_for_split_debuginfo_paths() {
|
||||
tcx.sess.source_map().path_mapping().map_prefix(f).0
|
||||
} else {
|
||||
f.into()
|
||||
}
|
||||
})
|
||||
let split_name = if tcx.sess.target_can_use_split_dwarf()
|
||||
&& let Some(f) = output_filenames.split_dwarf_path(
|
||||
tcx.sess.split_debuginfo(),
|
||||
tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
Some(codegen_unit_name),
|
||||
) {
|
||||
// We get a path relative to the working directory from split_dwarf_path
|
||||
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.unwrap_or_default();
|
||||
let split_name = split_name.to_str().unwrap();
|
||||
};
|
||||
let split_name = split_name
|
||||
.as_ref()
|
||||
.map(|f| f.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
|
||||
.unwrap_or_default();
|
||||
let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
|
||||
|
||||
let dwarf_version =
|
||||
|
@ -18,7 +18,9 @@ use crate::llvm;
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
use itertools::Itertools;
|
||||
use rustc_codegen_ssa::traits::TypeMembershipMethods;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_middle::ty::{Instance, Ty};
|
||||
use rustc_symbol_mangling::typeid::{
|
||||
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
|
||||
@ -141,33 +143,31 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
|
||||
if self.tcx.sess.is_sanitizer_cfi_enabled() {
|
||||
if let Some(instance) = instance {
|
||||
let typeid = typeid_for_instance(self.tcx, instance, TypeIdOptions::empty());
|
||||
self.set_type_metadata(llfn, typeid);
|
||||
let typeid =
|
||||
typeid_for_instance(self.tcx, instance, TypeIdOptions::GENERALIZE_POINTERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid =
|
||||
typeid_for_instance(self.tcx, instance, TypeIdOptions::NORMALIZE_INTEGERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid = typeid_for_instance(
|
||||
self.tcx,
|
||||
instance,
|
||||
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
|
||||
);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let mut typeids = FxIndexSet::default();
|
||||
for options in [
|
||||
TypeIdOptions::GENERALIZE_POINTERS,
|
||||
TypeIdOptions::NORMALIZE_INTEGERS,
|
||||
TypeIdOptions::NO_SELF_TYPE_ERASURE,
|
||||
]
|
||||
.into_iter()
|
||||
.powerset()
|
||||
.map(TypeIdOptions::from_iter)
|
||||
{
|
||||
let typeid = typeid_for_instance(self.tcx, instance, options);
|
||||
if typeids.insert(typeid.clone()) {
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
|
||||
self.set_type_metadata(llfn, typeid);
|
||||
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::GENERALIZE_POINTERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::NORMALIZE_INTEGERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid = typeid_for_fnabi(
|
||||
self.tcx,
|
||||
fn_abi,
|
||||
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
|
||||
);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
for options in
|
||||
[TypeIdOptions::GENERALIZE_POINTERS, TypeIdOptions::NORMALIZE_INTEGERS]
|
||||
.into_iter()
|
||||
.powerset()
|
||||
.map(TypeIdOptions::from_iter)
|
||||
{
|
||||
let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2089,14 +2089,14 @@ fn add_rpath_args(
|
||||
.map(|(path, _)| &**path)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut rpath_config = RPathConfig {
|
||||
let rpath_config = RPathConfig {
|
||||
libs: &*libs,
|
||||
out_filename: out_filename.to_path_buf(),
|
||||
has_rpath: sess.target.has_rpath,
|
||||
is_like_osx: sess.target.is_like_osx,
|
||||
linker_is_gnu: sess.target.linker_flavor.is_gnu(),
|
||||
};
|
||||
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
|
||||
cmd.args(&rpath::get_rpath_flags(&rpath_config));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ pub struct RPathConfig<'a> {
|
||||
pub linker_is_gnu: bool,
|
||||
}
|
||||
|
||||
pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<OsString> {
|
||||
pub fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec<OsString> {
|
||||
// No rpath on windows
|
||||
if !config.has_rpath {
|
||||
return Vec::new();
|
||||
@ -52,7 +52,7 @@ fn rpaths_to_flags(rpaths: Vec<OsString>) -> Vec<OsString> {
|
||||
ret
|
||||
}
|
||||
|
||||
fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<OsString> {
|
||||
fn get_rpaths(config: &RPathConfig<'_>) -> Vec<OsString> {
|
||||
debug!("output: {:?}", config.out_filename.display());
|
||||
debug!("libs:");
|
||||
for libpath in config.libs {
|
||||
@ -73,11 +73,11 @@ fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<OsString> {
|
||||
minimize_rpaths(&rpaths)
|
||||
}
|
||||
|
||||
fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<OsString> {
|
||||
fn get_rpaths_relative_to_output(config: &RPathConfig<'_>) -> Vec<OsString> {
|
||||
config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
|
||||
}
|
||||
|
||||
fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> OsString {
|
||||
fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsString {
|
||||
// Mac doesn't appear to support $ORIGIN
|
||||
let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" };
|
||||
|
||||
|
@ -871,7 +871,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
let mut parser = self.cx.new_parser_from_tts(toks);
|
||||
match parse_ast_fragment(&mut parser, kind) {
|
||||
Ok(fragment) => {
|
||||
ensure_complete_parse(&mut parser, path, kind.name(), span);
|
||||
ensure_complete_parse(&parser, path, kind.name(), span);
|
||||
fragment
|
||||
}
|
||||
Err(mut err) => {
|
||||
@ -958,7 +958,7 @@ pub fn parse_ast_fragment<'a>(
|
||||
}
|
||||
|
||||
pub fn ensure_complete_parse<'a>(
|
||||
parser: &mut Parser<'a>,
|
||||
parser: &Parser<'a>,
|
||||
macro_path: &ast::Path,
|
||||
kind_name: &str,
|
||||
span: Span,
|
||||
|
@ -529,6 +529,8 @@ declare_features! (
|
||||
(unstable, more_qualified_paths, "1.54.0", Some(86935)),
|
||||
/// Allows the `#[must_not_suspend]` attribute.
|
||||
(unstable, must_not_suspend, "1.57.0", Some(83310)),
|
||||
/// Allows `mut ref` and `mut ref mut` identifier patterns.
|
||||
(incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows using `#[naked]` on functions.
|
||||
(unstable, naked_functions, "1.9.0", Some(90957)),
|
||||
/// Allows specifying the as-needed link modifier
|
||||
|
@ -2733,9 +2733,9 @@ pub enum ImplicitSelfKind {
|
||||
/// Represents a `fn x(mut self);`.
|
||||
Mut,
|
||||
/// Represents a `fn x(&self);`.
|
||||
ImmRef,
|
||||
RefImm,
|
||||
/// Represents a `fn x(&mut self);`.
|
||||
MutRef,
|
||||
RefMut,
|
||||
/// Represents when a function does not have a self argument or
|
||||
/// when a function has a `self: X` argument.
|
||||
None,
|
||||
|
@ -14,14 +14,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
|
||||
&& matches!(borrow_kind, hir::BorrowKind::Ref)
|
||||
&& let Some(var) = is_path_static_mut(*expr)
|
||||
{
|
||||
handle_static_mut_ref(
|
||||
tcx,
|
||||
span,
|
||||
var,
|
||||
span.edition().at_least_rust_2024(),
|
||||
matches!(m, Mutability::Mut),
|
||||
hir_id,
|
||||
);
|
||||
handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +22,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
|
||||
pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
|
||||
if let hir::StmtKind::Let(loc) = stmt.kind
|
||||
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
|
||||
&& matches!(ba.0, rustc_ast::ByRef::Yes)
|
||||
&& let hir::ByRef::Yes(rmutbl) = ba.0
|
||||
&& let Some(init) = loc.init
|
||||
&& let Some(var) = is_path_static_mut(*init)
|
||||
{
|
||||
@ -38,7 +31,7 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
|
||||
init.span,
|
||||
var,
|
||||
loc.span.edition().at_least_rust_2024(),
|
||||
matches!(ba.1, Mutability::Mut),
|
||||
rmutbl,
|
||||
stmt.hir_id,
|
||||
);
|
||||
}
|
||||
@ -60,28 +53,27 @@ fn handle_static_mut_ref(
|
||||
span: Span,
|
||||
var: String,
|
||||
e2024: bool,
|
||||
mutable: bool,
|
||||
mutable: Mutability,
|
||||
hir_id: hir::HirId,
|
||||
) {
|
||||
if e2024 {
|
||||
let (sugg, shared) = if mutable {
|
||||
let (sugg, shared) = if mutable == Mutability::Mut {
|
||||
(errors::StaticMutRefSugg::Mut { span, var }, "mutable")
|
||||
} else {
|
||||
(errors::StaticMutRefSugg::Shared { span, var }, "shared")
|
||||
};
|
||||
tcx.sess.psess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared });
|
||||
return;
|
||||
}
|
||||
|
||||
let (sugg, shared) = if mutable {
|
||||
(errors::RefOfMutStaticSugg::Mut { span, var }, "mutable")
|
||||
} else {
|
||||
(errors::RefOfMutStaticSugg::Shared { span, var }, "shared")
|
||||
};
|
||||
tcx.emit_node_span_lint(
|
||||
STATIC_MUT_REFS,
|
||||
hir_id,
|
||||
span,
|
||||
errors::RefOfMutStatic { span, sugg, shared },
|
||||
);
|
||||
let (sugg, shared) = if mutable == Mutability::Mut {
|
||||
(errors::RefOfMutStaticSugg::Mut { span, var }, "mutable")
|
||||
} else {
|
||||
(errors::RefOfMutStaticSugg::Shared { span, var }, "shared")
|
||||
};
|
||||
tcx.emit_node_span_lint(
|
||||
STATIC_MUT_REFS,
|
||||
hir_id,
|
||||
span,
|
||||
errors::RefOfMutStatic { span, sugg, shared },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ fn resolve_local<'tcx>(
|
||||
// & expression, and its lifetime would be extended to the end of the block (due
|
||||
// to a different rule, not the below code).
|
||||
match pat.kind {
|
||||
PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true,
|
||||
PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes(_), _), ..) => true,
|
||||
|
||||
PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)),
|
||||
|
||||
|
@ -1721,12 +1721,15 @@ impl<'a> State<'a> {
|
||||
PatKind::Wild => self.word("_"),
|
||||
PatKind::Never => self.word("!"),
|
||||
PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => {
|
||||
if by_ref == ByRef::Yes {
|
||||
self.word_nbsp("ref");
|
||||
}
|
||||
if mutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
if let ByRef::Yes(rmutbl) = by_ref {
|
||||
self.word_nbsp("ref");
|
||||
if rmutbl.is_mut() {
|
||||
self.word_nbsp("mut");
|
||||
}
|
||||
}
|
||||
self.print_ident(ident);
|
||||
if let Some(p) = sub {
|
||||
self.word("@");
|
||||
|
@ -739,12 +739,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
// In a cases of pattern like `let pat = upvar`, don't use the span
|
||||
// of the pattern, as this just looks confusing, instead use the span
|
||||
// of the discriminant.
|
||||
match bm {
|
||||
ty::BindByReference(m) => {
|
||||
match bm.0 {
|
||||
hir::ByRef::Yes(m) => {
|
||||
let bk = ty::BorrowKind::from_mutbl(m);
|
||||
delegate.borrow(place, discr_place.hir_id, bk);
|
||||
}
|
||||
ty::BindByValue(..) => {
|
||||
hir::ByRef::No => {
|
||||
debug!("walk_pat binding consuming pat");
|
||||
delegate_consume(mc, *delegate, place, discr_place.hir_id);
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
.get(pat.hir_id)
|
||||
.expect("missing binding mode");
|
||||
|
||||
if let ty::BindByReference(_) = bm {
|
||||
if matches!(bm.0, hir::ByRef::Yes(_)) {
|
||||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
|
@ -5,14 +5,13 @@ use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{
|
||||
codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc_hir::{HirId, Pat, PatKind};
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt};
|
||||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
@ -79,7 +78,7 @@ struct TopInfo<'tcx> {
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct PatInfo<'tcx, 'a> {
|
||||
binding_mode: BindingMode,
|
||||
binding_mode: BindingAnnotation,
|
||||
top_info: TopInfo<'tcx>,
|
||||
decl_origin: Option<DeclOrigin<'a>>,
|
||||
|
||||
@ -124,7 +123,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not);
|
||||
const INITIAL_BM: BindingAnnotation = BindingAnnotation(ByRef::No, Mutability::Not);
|
||||
|
||||
/// Mode for adjusting the expected type and binding mode.
|
||||
enum AdjustMode {
|
||||
@ -269,9 +268,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
def_bm: BindingMode,
|
||||
def_bm: BindingAnnotation,
|
||||
adjust_mode: AdjustMode,
|
||||
) -> (Ty<'tcx>, BindingMode) {
|
||||
) -> (Ty<'tcx>, BindingAnnotation) {
|
||||
match adjust_mode {
|
||||
AdjustMode::Pass => (expected, def_bm),
|
||||
AdjustMode::Reset => (expected, INITIAL_BM),
|
||||
@ -354,8 +353,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
mut def_bm: BindingMode,
|
||||
) -> (Ty<'tcx>, BindingMode) {
|
||||
mut def_bm: BindingAnnotation,
|
||||
) -> (Ty<'tcx>, BindingAnnotation) {
|
||||
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
|
||||
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
|
||||
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
|
||||
@ -374,15 +373,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pat_adjustments.push(expected);
|
||||
|
||||
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
|
||||
def_bm = ty::BindByReference(match def_bm {
|
||||
def_bm.0 = ByRef::Yes(match def_bm.0 {
|
||||
// If default binding mode is by value, make it `ref` or `ref mut`
|
||||
// (depending on whether we observe `&` or `&mut`).
|
||||
ty::BindByValue(_) |
|
||||
ByRef::No |
|
||||
// When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
|
||||
ty::BindByReference(hir::Mutability::Mut) => inner_mutability,
|
||||
ByRef::Yes(Mutability::Mut) => inner_mutability,
|
||||
// Once a `ref`, always a `ref`.
|
||||
// This is because a `& &mut` cannot mutate the underlying value.
|
||||
ty::BindByReference(m @ hir::Mutability::Not) => m,
|
||||
ByRef::Yes(Mutability::Not) => Mutability::Not,
|
||||
});
|
||||
}
|
||||
|
||||
@ -599,7 +598,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
fn check_pat_ident(
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
ba: hir::BindingAnnotation,
|
||||
ba: BindingAnnotation,
|
||||
var_id: HirId,
|
||||
sub: Option<&'tcx Pat<'tcx>>,
|
||||
expected: Ty<'tcx>,
|
||||
@ -609,8 +608,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// Determine the binding mode...
|
||||
let bm = match ba {
|
||||
hir::BindingAnnotation::NONE => def_bm,
|
||||
_ => BindingMode::convert(ba),
|
||||
BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
|
||||
_ => ba,
|
||||
};
|
||||
// ...and store it in a side table:
|
||||
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
|
||||
@ -618,8 +617,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
|
||||
|
||||
let local_ty = self.local_ty(pat.span, pat.hir_id);
|
||||
let eq_ty = match bm {
|
||||
ty::BindByReference(mutbl) => {
|
||||
let eq_ty = match bm.0 {
|
||||
ByRef::Yes(mutbl) => {
|
||||
// If the binding is like `ref x | ref mut x`,
|
||||
// then `x` is assigned a value of type `&M T` where M is the
|
||||
// mutability and T is the expected type.
|
||||
@ -630,10 +629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.new_ref_ty(pat.span, mutbl, expected)
|
||||
}
|
||||
// Otherwise, the type of x is the expected type `T`.
|
||||
ty::BindByValue(_) => {
|
||||
// As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
|
||||
expected
|
||||
}
|
||||
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
|
||||
};
|
||||
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
@ -655,7 +651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// bindings have the same type by comparing them all against the type of that first pat.
|
||||
fn check_binding_alt_eq_ty(
|
||||
&self,
|
||||
ba: hir::BindingAnnotation,
|
||||
ba: BindingAnnotation,
|
||||
span: Span,
|
||||
var_id: HirId,
|
||||
ty: Ty<'tcx>,
|
||||
@ -695,10 +691,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ba: hir::BindingAnnotation,
|
||||
ba: BindingAnnotation,
|
||||
) {
|
||||
match (expected.kind(), actual.kind(), ba) {
|
||||
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
|
||||
(ty::Ref(_, inner_ty, _), _, BindingAnnotation::NONE)
|
||||
if self.can_eq(self.param_env, *inner_ty, actual) =>
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
@ -708,7 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
|
||||
(_, ty::Ref(_, inner_ty, _), BindingAnnotation::REF)
|
||||
if self.can_eq(self.param_env, expected, *inner_ty) =>
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
@ -800,7 +796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let PatKind::Ref(the_ref, _) = i.kind
|
||||
&& let PatKind::Binding(mt, _, ident, _) = the_ref.kind
|
||||
{
|
||||
let hir::BindingAnnotation(_, mtblty) = mt;
|
||||
let BindingAnnotation(_, mtblty) = mt;
|
||||
err.span_suggestion_verbose(
|
||||
i.span,
|
||||
format!("consider removing `&{mutability}` from the pattern"),
|
||||
@ -2037,7 +2033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
pat: &'tcx Pat<'tcx>,
|
||||
inner: &'tcx Pat<'tcx>,
|
||||
mutbl: hir::Mutability,
|
||||
mutbl: Mutability,
|
||||
expected: Ty<'tcx>,
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> Ty<'tcx> {
|
||||
@ -2088,7 +2084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
/// Create a reference type with a fresh region variable.
|
||||
fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let region = self.next_region_var(infer::PatternRegion(span));
|
||||
Ty::new_ref(self.tcx, region, ty, mutbl)
|
||||
}
|
||||
|
@ -1711,10 +1711,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let bm = *typeck_results.pat_binding_modes().get(var_hir_id).expect("missing binding mode");
|
||||
|
||||
let mut is_mutbl = match bm {
|
||||
ty::BindByValue(mutability) => mutability,
|
||||
ty::BindByReference(_) => hir::Mutability::Not,
|
||||
};
|
||||
let mut is_mutbl = bm.1;
|
||||
|
||||
for pointer_ty in place.deref_tys() {
|
||||
match pointer_ty.kind() {
|
||||
|
@ -13,7 +13,7 @@ use ut::UnifyKey;
|
||||
use std::ops::Range;
|
||||
|
||||
fn vars_since_snapshot<'tcx, T>(
|
||||
table: &mut UnificationTable<'_, 'tcx, T>,
|
||||
table: &UnificationTable<'_, 'tcx, T>,
|
||||
snapshot_var_len: usize,
|
||||
) -> Range<T>
|
||||
where
|
||||
@ -124,11 +124,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let type_vars =
|
||||
inner.type_variables().vars_since_snapshot(variable_lengths.type_var_len);
|
||||
let int_vars = vars_since_snapshot(
|
||||
&mut inner.int_unification_table(),
|
||||
&inner.int_unification_table(),
|
||||
variable_lengths.int_var_len,
|
||||
);
|
||||
let float_vars = vars_since_snapshot(
|
||||
&mut inner.float_unification_table(),
|
||||
&inner.float_unification_table(),
|
||||
variable_lengths.float_var_len,
|
||||
);
|
||||
let region_vars = inner
|
||||
|
@ -1668,14 +1668,16 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
|
||||
Cast {
|
||||
deref_left: &'a str,
|
||||
deref_right: &'a str,
|
||||
#[suggestion_part(code = "{deref_left}")]
|
||||
paren_left: &'a str,
|
||||
paren_right: &'a str,
|
||||
#[suggestion_part(code = "({deref_left}")]
|
||||
left_before: Option<Span>,
|
||||
#[suggestion_part(code = " as *const ()")]
|
||||
left: Span,
|
||||
#[suggestion_part(code = "{deref_right}")]
|
||||
#[suggestion_part(code = "{paren_left}.cast::<()>()")]
|
||||
left_after: Span,
|
||||
#[suggestion_part(code = "({deref_right}")]
|
||||
right_before: Option<Span>,
|
||||
#[suggestion_part(code = " as *const ()")]
|
||||
right: Span,
|
||||
#[suggestion_part(code = "{paren_right}.cast::<()>()")]
|
||||
right_after: Span,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -657,10 +657,16 @@ fn lint_nan<'tcx>(
|
||||
cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ComparisonOp {
|
||||
BinOp(hir::BinOpKind),
|
||||
Other,
|
||||
}
|
||||
|
||||
fn lint_wide_pointer<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx hir::Expr<'tcx>,
|
||||
binop: hir::BinOpKind,
|
||||
cmpop: ComparisonOp,
|
||||
l: &'tcx hir::Expr<'tcx>,
|
||||
r: &'tcx hir::Expr<'tcx>,
|
||||
) {
|
||||
@ -679,7 +685,7 @@ fn lint_wide_pointer<'tcx>(
|
||||
}
|
||||
};
|
||||
|
||||
// PartialEq::{eq,ne} takes references, remove any explicit references
|
||||
// the left and right operands can have references, remove any explicit references
|
||||
let l = l.peel_borrows();
|
||||
let r = r.peel_borrows();
|
||||
|
||||
@ -707,8 +713,8 @@ fn lint_wide_pointer<'tcx>(
|
||||
);
|
||||
};
|
||||
|
||||
let ne = if binop == hir::BinOpKind::Ne { "!" } else { "" };
|
||||
let is_eq_ne = matches!(binop, hir::BinOpKind::Eq | hir::BinOpKind::Ne);
|
||||
let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" };
|
||||
let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne));
|
||||
let is_dyn_comparison = l_inner_ty_is_dyn && r_inner_ty_is_dyn;
|
||||
|
||||
let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
|
||||
@ -745,12 +751,12 @@ fn lint_wide_pointer<'tcx>(
|
||||
AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
|
||||
deref_left,
|
||||
deref_right,
|
||||
// those two Options are required for correctness as having
|
||||
// an empty span and an empty suggestion is not permitted
|
||||
left_before: (l_ty_refs != 0).then_some(left),
|
||||
right_before: (r_ty_refs != 0).then(|| r_span.shrink_to_lo()),
|
||||
left: l_span.shrink_to_hi(),
|
||||
right,
|
||||
paren_left: if l_ty_refs != 0 { ")" } else { "" },
|
||||
paren_right: if r_ty_refs != 0 { ")" } else { "" },
|
||||
left_before: (l_ty_refs != 0).then_some(l_span.shrink_to_lo()),
|
||||
left_after: l_span.shrink_to_hi(),
|
||||
right_before: (r_ty_refs != 0).then_some(r_span.shrink_to_lo()),
|
||||
right_after: r_span.shrink_to_hi(),
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -773,7 +779,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
|
||||
} else {
|
||||
lint_nan(cx, e, binop, l, r);
|
||||
lint_wide_pointer(cx, e, binop.node, l, r);
|
||||
lint_wide_pointer(cx, e, ComparisonOp::BinOp(binop.node), l, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -782,16 +788,16 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& let Some(binop) = partialeq_binop(diag_item) =>
|
||||
&& let Some(cmpop) = diag_item_cmpop(diag_item) =>
|
||||
{
|
||||
lint_wide_pointer(cx, e, binop, l, r);
|
||||
lint_wide_pointer(cx, e, cmpop, l, r);
|
||||
}
|
||||
hir::ExprKind::MethodCall(_, l, [r], _)
|
||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
|
||||
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& let Some(binop) = partialeq_binop(diag_item) =>
|
||||
&& let Some(cmpop) = diag_item_cmpop(diag_item) =>
|
||||
{
|
||||
lint_wide_pointer(cx, e, binop, l, r);
|
||||
lint_wide_pointer(cx, e, cmpop, l, r);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@ -876,14 +882,20 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
)
|
||||
}
|
||||
|
||||
fn partialeq_binop(diag_item: Symbol) -> Option<hir::BinOpKind> {
|
||||
if diag_item == sym::cmp_partialeq_eq {
|
||||
Some(hir::BinOpKind::Eq)
|
||||
} else if diag_item == sym::cmp_partialeq_ne {
|
||||
Some(hir::BinOpKind::Ne)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn diag_item_cmpop(diag_item: Symbol) -> Option<ComparisonOp> {
|
||||
Some(match diag_item {
|
||||
sym::cmp_ord_max => ComparisonOp::Other,
|
||||
sym::cmp_ord_min => ComparisonOp::Other,
|
||||
sym::ord_cmp_method => ComparisonOp::Other,
|
||||
sym::cmp_partialeq_eq => ComparisonOp::BinOp(hir::BinOpKind::Eq),
|
||||
sym::cmp_partialeq_ne => ComparisonOp::BinOp(hir::BinOpKind::Ne),
|
||||
sym::cmp_partialord_cmp => ComparisonOp::Other,
|
||||
sym::cmp_partialord_ge => ComparisonOp::BinOp(hir::BinOpKind::Ge),
|
||||
sym::cmp_partialord_gt => ComparisonOp::BinOp(hir::BinOpKind::Gt),
|
||||
sym::cmp_partialord_le => ComparisonOp::BinOp(hir::BinOpKind::Le),
|
||||
sym::cmp_partialord_lt => ComparisonOp::BinOp(hir::BinOpKind::Lt),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -549,17 +549,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
match source_file.name {
|
||||
FileName::Real(ref original_file_name) => {
|
||||
let adapted_file_name = if self.tcx.sess.should_prefer_remapped_for_codegen() {
|
||||
source_map.path_mapping().to_embeddable_absolute_path(
|
||||
original_file_name.clone(),
|
||||
working_directory,
|
||||
)
|
||||
} else {
|
||||
source_map.path_mapping().to_local_embeddable_absolute_path(
|
||||
original_file_name.clone(),
|
||||
working_directory,
|
||||
)
|
||||
};
|
||||
// FIXME: This should probably to conditionally remapped under
|
||||
// a RemapPathScopeComponents but which one?
|
||||
let adapted_file_name = source_map
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(original_file_name.clone(), working_directory);
|
||||
|
||||
adapted_source_file.name = FileName::Real(adapted_file_name);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{HasDataLayout, Size};
|
||||
|
||||
@ -516,7 +516,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
self.const_caller_location(
|
||||
rustc_span::symbol::Symbol::intern(
|
||||
&caller.file.name.for_codegen(self.sess).to_string_lossy(),
|
||||
&caller
|
||||
.file
|
||||
.name
|
||||
.for_scope(self.sess, RemapPathScopeComponents::MACRO)
|
||||
.to_string_lossy(),
|
||||
),
|
||||
caller.line as u32,
|
||||
caller.col_display as u32 + 1,
|
||||
|
@ -17,8 +17,10 @@ use rustc_data_structures::captures::Captures;
|
||||
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||
use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_hir::{
|
||||
self as hir, BindingAnnotation, ByRef, CoroutineDesugaring, CoroutineKind, HirId,
|
||||
ImplicitSelfKind,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
@ -992,8 +994,8 @@ pub enum LocalKind {
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
pub struct VarBindingForm<'tcx> {
|
||||
/// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
|
||||
pub binding_mode: ty::BindingMode,
|
||||
/// Is variable bound via `x`, `mut x`, `ref x`, `ref mut x`, `mut ref x`, or `mut ref mut x`?
|
||||
pub binding_mode: BindingAnnotation,
|
||||
/// If an explicit type was provided for this variable binding,
|
||||
/// this holds the source Span of that type.
|
||||
///
|
||||
@ -1218,7 +1220,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
self.local_info(),
|
||||
LocalInfo::User(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
binding_mode: BindingAnnotation(ByRef::No, _),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
@ -1235,7 +1237,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
self.local_info(),
|
||||
LocalInfo::User(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
binding_mode: BindingAnnotation(ByRef::No, _),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
|
@ -12,12 +12,12 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::RangeEnd;
|
||||
use rustc_hir::{BindingAnnotation, ByRef, RangeEnd};
|
||||
use rustc_index::newtype_index;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::interpret::{AllocId, Scalar};
|
||||
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
|
||||
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{
|
||||
@ -581,12 +581,6 @@ pub enum InlineAsmOperand<'tcx> {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
|
||||
pub enum BindingMode {
|
||||
ByValue,
|
||||
ByRef(BorrowKind),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable, TypeVisitable)]
|
||||
pub struct FieldPat<'tcx> {
|
||||
pub field: FieldIdx,
|
||||
@ -607,19 +601,22 @@ impl<'tcx> Pat<'tcx> {
|
||||
|
||||
pub fn simple_ident(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
|
||||
Some(name)
|
||||
}
|
||||
PatKind::Binding {
|
||||
name,
|
||||
mode: BindingAnnotation(ByRef::No, _),
|
||||
subpattern: None,
|
||||
..
|
||||
} => Some(name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
||||
/// `match foo() { Some(a) => (), None => () }`
|
||||
pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) {
|
||||
pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) {
|
||||
self.walk_always(|p| {
|
||||
if let PatKind::Binding { name, mode, ty, .. } = p.kind {
|
||||
f(name, mode, ty, p.span);
|
||||
f(name, mode.0, ty, p.span);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -730,10 +727,9 @@ pub enum PatKind<'tcx> {
|
||||
|
||||
/// `x`, `ref x`, `x @ P`, etc.
|
||||
Binding {
|
||||
mutability: Mutability,
|
||||
name: Symbol,
|
||||
#[type_visitable(ignore)]
|
||||
mode: BindingMode,
|
||||
mode: BindingAnnotation,
|
||||
#[type_visitable(ignore)]
|
||||
var: LocalVarId,
|
||||
ty: Ty<'tcx>,
|
||||
@ -1073,17 +1069,8 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
|
||||
PatKind::Wild => write!(f, "_"),
|
||||
PatKind::Never => write!(f, "!"),
|
||||
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
|
||||
PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
|
||||
let is_mut = match mode {
|
||||
BindingMode::ByValue => mutability == Mutability::Mut,
|
||||
BindingMode::ByRef(bk) => {
|
||||
write!(f, "ref ")?;
|
||||
matches!(bk, BorrowKind::Mut { .. })
|
||||
}
|
||||
};
|
||||
if is_mut {
|
||||
write!(f, "mut ")?;
|
||||
}
|
||||
PatKind::Binding { name, mode, ref subpattern, .. } => {
|
||||
f.write_str(mode.prefix_str())?;
|
||||
write!(f, "{name}")?;
|
||||
if let Some(ref subpattern) = *subpattern {
|
||||
write!(f, " @ {subpattern}")?;
|
||||
|
@ -230,15 +230,7 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
||||
AscribeUserType { subpattern, ascription: _ }
|
||||
| Deref { subpattern }
|
||||
| DerefPattern { subpattern }
|
||||
| Binding {
|
||||
subpattern: Some(subpattern),
|
||||
mutability: _,
|
||||
mode: _,
|
||||
var: _,
|
||||
ty: _,
|
||||
is_primary: _,
|
||||
name: _,
|
||||
} => visitor.visit_pat(subpattern),
|
||||
| Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern),
|
||||
Binding { .. } | Wild | Never | Error(_) => {}
|
||||
Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
|
@ -1,18 +0,0 @@
|
||||
use rustc_hir::{BindingAnnotation, ByRef, Mutability};
|
||||
|
||||
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)]
|
||||
pub enum BindingMode {
|
||||
BindByReference(Mutability),
|
||||
BindByValue(Mutability),
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! { BindingMode }
|
||||
|
||||
impl BindingMode {
|
||||
pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode {
|
||||
match by_ref {
|
||||
ByRef::No => BindingMode::BindByValue(mutbl),
|
||||
ByRef::Yes => BindingMode::BindByReference(mutbl),
|
||||
}
|
||||
}
|
||||
}
|
@ -76,8 +76,6 @@ pub use rustc_type_ir::ConstKind::{
|
||||
};
|
||||
pub use rustc_type_ir::*;
|
||||
|
||||
pub use self::binding::BindingMode;
|
||||
pub use self::binding::BindingMode::*;
|
||||
pub use self::closure::{
|
||||
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
|
||||
CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
|
||||
@ -123,7 +121,6 @@ pub use self::typeck_results::{
|
||||
pub mod _match;
|
||||
pub mod abstract_const;
|
||||
pub mod adjustment;
|
||||
pub mod binding;
|
||||
pub mod cast;
|
||||
pub mod codec;
|
||||
pub mod error;
|
||||
|
@ -402,6 +402,7 @@ TrivialTypeTraversalImpls! {
|
||||
::rustc_span::symbol::Symbol,
|
||||
::rustc_hir::def::Res,
|
||||
::rustc_hir::def_id::LocalDefId,
|
||||
::rustc_hir::ByRef,
|
||||
::rustc_hir::HirId,
|
||||
::rustc_hir::MatchSource,
|
||||
::rustc_target::asm::InlineAsmRegOrRegClass,
|
||||
|
@ -3,8 +3,8 @@ use crate::{
|
||||
infer::canonical::Canonical,
|
||||
traits::ObligationCause,
|
||||
ty::{
|
||||
self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
|
||||
GenericArgKind, GenericArgs, GenericArgsRef, Ty, UserArgs,
|
||||
self, tls, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind,
|
||||
GenericArgs, GenericArgsRef, Ty, UserArgs,
|
||||
},
|
||||
};
|
||||
use rustc_data_structures::{
|
||||
@ -12,12 +12,12 @@ use rustc_data_structures::{
|
||||
unord::{ExtendUnord, UnordItems, UnordSet},
|
||||
};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{
|
||||
self as hir,
|
||||
def::{DefKind, Res},
|
||||
def_id::{DefId, LocalDefId, LocalDefIdMap},
|
||||
hir_id::OwnerId,
|
||||
HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
|
||||
BindingAnnotation, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
|
||||
};
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
@ -78,8 +78,8 @@ pub struct TypeckResults<'tcx> {
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
pat_binding_modes: ItemLocalMap<BindingMode>,
|
||||
/// Stores the actual binding mode for all instances of [`BindingAnnotation`].
|
||||
pat_binding_modes: ItemLocalMap<BindingAnnotation>,
|
||||
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes
|
||||
/// for later usage in THIR lowering. For example,
|
||||
@ -408,17 +408,22 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
pub fn extract_binding_mode(
|
||||
&self,
|
||||
s: &Session,
|
||||
id: HirId,
|
||||
sp: Span,
|
||||
) -> Option<BindingAnnotation> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.dcx().span_bug(sp, "missing binding mode");
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingAnnotation> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingAnnotation> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
|
||||
}
|
||||
|
||||
@ -442,7 +447,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
let mut has_ref_mut = false;
|
||||
pat.walk(|pat| {
|
||||
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
|
||||
&& let Some(ty::BindByReference(ty::Mutability::Mut)) =
|
||||
&& let Some(BindingAnnotation(ByRef::Yes(Mutability::Mut), _)) =
|
||||
self.pat_binding_modes().get(id)
|
||||
{
|
||||
has_ref_mut = true;
|
||||
|
@ -218,7 +218,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.visit_primary_bindings(
|
||||
pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, _, _, _, node, span, _, _| {
|
||||
&mut |this, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(
|
||||
block,
|
||||
node,
|
||||
@ -308,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.visit_primary_bindings(
|
||||
pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, _, _, _, node, span, _, _| {
|
||||
&mut |this, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||
},
|
||||
|
@ -14,6 +14,7 @@ use rustc_data_structures::{
|
||||
fx::{FxHashSet, FxIndexMap, FxIndexSet},
|
||||
stack::ensure_sufficient_stack,
|
||||
};
|
||||
use rustc_hir::{BindingAnnotation, ByRef};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::{self, *};
|
||||
use rustc_middle::thir::{self, *};
|
||||
@ -554,7 +555,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
) -> BlockAnd<()> {
|
||||
match irrefutable_pat.kind {
|
||||
// Optimize the case of `let x = ...` to write directly into `x`
|
||||
PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
|
||||
PatKind::Binding {
|
||||
mode: BindingAnnotation(ByRef::No, _),
|
||||
var,
|
||||
subpattern: None,
|
||||
..
|
||||
} => {
|
||||
let place =
|
||||
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
|
||||
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
||||
@ -580,7 +586,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
box Pat {
|
||||
kind:
|
||||
PatKind::Binding {
|
||||
mode: BindingMode::ByValue, var, subpattern: None, ..
|
||||
mode: BindingAnnotation(ByRef::No, _),
|
||||
var,
|
||||
subpattern: None,
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
@ -720,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.visit_primary_bindings(
|
||||
pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
&mut |this, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
visibility_scope =
|
||||
Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
|
||||
@ -730,7 +739,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.declare_binding(
|
||||
source_info,
|
||||
visibility_scope,
|
||||
mutability,
|
||||
name,
|
||||
mode,
|
||||
var,
|
||||
@ -818,9 +826,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pattern_user_ty: UserTypeProjections,
|
||||
f: &mut impl FnMut(
|
||||
&mut Self,
|
||||
Mutability,
|
||||
Symbol,
|
||||
BindingMode,
|
||||
BindingAnnotation,
|
||||
LocalVarId,
|
||||
Span,
|
||||
Ty<'tcx>,
|
||||
@ -832,18 +839,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pattern, pattern_user_ty
|
||||
);
|
||||
match pattern.kind {
|
||||
PatKind::Binding {
|
||||
mutability,
|
||||
name,
|
||||
mode,
|
||||
var,
|
||||
ty,
|
||||
ref subpattern,
|
||||
is_primary,
|
||||
..
|
||||
} => {
|
||||
PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => {
|
||||
if is_primary {
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
|
||||
f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
|
||||
}
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty, f);
|
||||
@ -1079,7 +1077,7 @@ struct Binding<'tcx> {
|
||||
span: Span,
|
||||
source: Place<'tcx>,
|
||||
var_id: LocalVarId,
|
||||
binding_mode: BindingMode,
|
||||
binding_mode: BindingAnnotation,
|
||||
}
|
||||
|
||||
/// Indicates that the type of `source` must be a subtype of the
|
||||
@ -1595,10 +1593,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// [`Switch`]: TestKind::Switch
|
||||
/// [`SwitchInt`]: TestKind::SwitchInt
|
||||
/// [`Range`]: TestKind::Range
|
||||
fn pick_test(
|
||||
&mut self,
|
||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||
) -> (Place<'tcx>, Test<'tcx>) {
|
||||
fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
|
||||
// Extract the match-pair from the highest priority candidate
|
||||
let match_pair = &candidates.first().unwrap().match_pairs[0];
|
||||
let test = self.test(match_pair);
|
||||
@ -2097,9 +2092,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings);
|
||||
|
||||
self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
|
||||
let guard_frame = GuardFrame {
|
||||
locals: bindings.map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode)).collect(),
|
||||
};
|
||||
let guard_frame =
|
||||
GuardFrame { locals: bindings.map(|b| GuardFrameLocal::new(b.var_id)).collect() };
|
||||
debug!("entering guard building context: {:?}", guard_frame);
|
||||
self.guard_context.push(guard_frame);
|
||||
|
||||
@ -2176,7 +2170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
.iter()
|
||||
.flat_map(|d| &d.bindings)
|
||||
.chain(&candidate.extra_data.bindings)
|
||||
.filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue));
|
||||
.filter(|binding| matches!(binding.binding_mode.0, ByRef::No));
|
||||
// Read all of the by reference bindings to ensure that the
|
||||
// place they refer to can't be modified by the guard.
|
||||
for binding in by_value_bindings.clone() {
|
||||
@ -2263,12 +2257,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
RefWithinGuard,
|
||||
schedule_drops,
|
||||
);
|
||||
match binding.binding_mode {
|
||||
BindingMode::ByValue => {
|
||||
match binding.binding_mode.0 {
|
||||
ByRef::No => {
|
||||
let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, binding.source);
|
||||
self.cfg.push_assign(block, source_info, ref_for_guard, rvalue);
|
||||
}
|
||||
BindingMode::ByRef(borrow_kind) => {
|
||||
ByRef::Yes(mutbl) => {
|
||||
let value_for_arm = self.storage_live_binding(
|
||||
block,
|
||||
binding.var_id,
|
||||
@ -2277,7 +2271,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
schedule_drops,
|
||||
);
|
||||
|
||||
let rvalue = Rvalue::Ref(re_erased, borrow_kind, binding.source);
|
||||
let rvalue =
|
||||
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
|
||||
self.cfg.push_assign(block, source_info, value_for_arm, rvalue);
|
||||
let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, value_for_arm);
|
||||
self.cfg.push_assign(block, source_info, ref_for_guard, rvalue);
|
||||
@ -2318,10 +2313,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if schedule_drops {
|
||||
self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
|
||||
}
|
||||
let rvalue = match binding.binding_mode {
|
||||
BindingMode::ByValue => Rvalue::Use(self.consume_by_copy_or_move(binding.source)),
|
||||
BindingMode::ByRef(borrow_kind) => {
|
||||
Rvalue::Ref(re_erased, borrow_kind, binding.source)
|
||||
let rvalue = match binding.binding_mode.0 {
|
||||
ByRef::No => Rvalue::Use(self.consume_by_copy_or_move(binding.source)),
|
||||
ByRef::Yes(mutbl) => {
|
||||
Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source)
|
||||
}
|
||||
};
|
||||
self.cfg.push_assign(block, source_info, local, rvalue);
|
||||
@ -2338,9 +2333,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
source_info: SourceInfo,
|
||||
visibility_scope: SourceScope,
|
||||
mutability: Mutability,
|
||||
name: Symbol,
|
||||
mode: BindingMode,
|
||||
mode: BindingAnnotation,
|
||||
var_id: LocalVarId,
|
||||
var_ty: Ty<'tcx>,
|
||||
user_ty: UserTypeProjections,
|
||||
@ -2350,18 +2344,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
|
||||
let binding_mode = match mode {
|
||||
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
|
||||
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
|
||||
};
|
||||
let local = LocalDecl {
|
||||
mutability,
|
||||
mutability: mode.1,
|
||||
ty: var_ty,
|
||||
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
|
||||
source_info,
|
||||
local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
|
||||
VarBindingForm {
|
||||
binding_mode,
|
||||
binding_mode: mode,
|
||||
// hypothetically, `visit_primary_bindings` could try to unzip
|
||||
// an outermost hir::Ty as we descend, matching up
|
||||
// idents in pat; but complex w/ unclear UI payoff.
|
||||
|
@ -154,15 +154,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
TestCase::Irrefutable { ascription, binding: None }
|
||||
}
|
||||
|
||||
PatKind::Binding {
|
||||
name: _,
|
||||
mutability: _,
|
||||
mode,
|
||||
var,
|
||||
ty: _,
|
||||
ref subpattern,
|
||||
is_primary: _,
|
||||
} => {
|
||||
PatKind::Binding { mode, var, ref subpattern, .. } => {
|
||||
let binding = place.map(|source| super::Binding {
|
||||
span: pattern.span,
|
||||
source,
|
||||
@ -347,3 +339,11 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
|
||||
match ref_mutability {
|
||||
Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||
Mutability::Not => BorrowKind::Shared,
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,9 @@ use rustc_ast::attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node};
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
@ -19,9 +18,7 @@ use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::thir::{
|
||||
self, BindingMode, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
|
||||
};
|
||||
use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
@ -337,7 +334,7 @@ struct GuardFrameLocal {
|
||||
}
|
||||
|
||||
impl GuardFrameLocal {
|
||||
fn new(id: LocalVarId, _binding_mode: BindingMode) -> Self {
|
||||
fn new(id: LocalVarId) -> Self {
|
||||
GuardFrameLocal { id }
|
||||
}
|
||||
}
|
||||
@ -967,9 +964,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
match pat.kind {
|
||||
// Don't introduce extra copies for simple bindings
|
||||
PatKind::Binding {
|
||||
mutability,
|
||||
var,
|
||||
mode: BindingMode::ByValue,
|
||||
mode: BindingAnnotation(ByRef::No, mutability),
|
||||
subpattern: None,
|
||||
..
|
||||
} => {
|
||||
@ -979,7 +975,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if let Some(kind) = param.self_kind {
|
||||
LocalInfo::User(BindingForm::ImplicitSelf(kind))
|
||||
} else {
|
||||
let binding_mode = ty::BindingMode::BindByValue(mutability);
|
||||
let binding_mode = BindingAnnotation(ByRef::No, mutability);
|
||||
LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
binding_mode,
|
||||
opt_ty_info: param.ty_span,
|
||||
|
@ -2,11 +2,11 @@ use std::borrow::Cow;
|
||||
|
||||
use crate::build::ExprCategory;
|
||||
use crate::errors::*;
|
||||
use rustc_middle::thir::visit::Visitor;
|
||||
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, Mutability};
|
||||
use rustc_middle::mir::BorrowKind;
|
||||
use rustc_middle::thir::visit::Visitor;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
||||
@ -289,22 +289,22 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||
visit::walk_pat(self, pat);
|
||||
}
|
||||
}
|
||||
PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => {
|
||||
PatKind::Binding { mode: BindingAnnotation(ByRef::Yes(rm), _), ty, .. } => {
|
||||
if self.inside_adt {
|
||||
let ty::Ref(_, ty, _) = ty.kind() else {
|
||||
span_bug!(
|
||||
pat.span,
|
||||
"BindingMode::ByRef in pattern, but found non-reference type {}",
|
||||
"ByRef::Yes in pattern, but found non-reference type {}",
|
||||
ty
|
||||
);
|
||||
};
|
||||
match borrow_kind {
|
||||
BorrowKind::Fake | BorrowKind::Shared => {
|
||||
match rm {
|
||||
Mutability::Not => {
|
||||
if !ty.is_freeze(self.tcx, self.param_env) {
|
||||
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
|
||||
}
|
||||
}
|
||||
BorrowKind::Mut { .. } => {
|
||||
Mutability::Mut { .. } => {
|
||||
self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField);
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,9 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{
|
||||
codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::*;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId};
|
||||
use rustc_middle::middle::limits::get_limit_size;
|
||||
use rustc_middle::thir::visit::Visitor;
|
||||
use rustc_middle::thir::*;
|
||||
@ -723,13 +722,14 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
||||
let sess = cx.tcx.sess;
|
||||
|
||||
// Get the binding move, extract the mutability if by-ref.
|
||||
let mut_outer = match mode {
|
||||
BindingMode::ByValue if is_binding_by_move(ty) => {
|
||||
let mut_outer = match mode.0 {
|
||||
ByRef::No if is_binding_by_move(ty) => {
|
||||
// We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
|
||||
let mut conflicts_ref = Vec::new();
|
||||
sub.each_binding(|_, mode, _, span| match mode {
|
||||
BindingMode::ByValue => {}
|
||||
BindingMode::ByRef(_) => conflicts_ref.push(span),
|
||||
sub.each_binding(|_, mode, _, span| {
|
||||
if matches!(mode, ByRef::Yes(_)) {
|
||||
conflicts_ref.push(span)
|
||||
}
|
||||
});
|
||||
if !conflicts_ref.is_empty() {
|
||||
sess.dcx().emit_err(BorrowOfMovedValue {
|
||||
@ -742,8 +742,8 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
||||
}
|
||||
return;
|
||||
}
|
||||
BindingMode::ByValue => return,
|
||||
BindingMode::ByRef(m) => m.mutability(),
|
||||
ByRef::No => return,
|
||||
ByRef::Yes(m) => m,
|
||||
};
|
||||
|
||||
// We now have `ref $mut_outer binding @ sub` (semantically).
|
||||
@ -753,7 +753,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
||||
let mut conflicts_mut_ref = Vec::new();
|
||||
sub.each_binding(|name, mode, ty, span| {
|
||||
match mode {
|
||||
BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) {
|
||||
ByRef::Yes(mut_inner) => match (mut_outer, mut_inner) {
|
||||
// Both sides are `ref`.
|
||||
(Mutability::Not, Mutability::Not) => {}
|
||||
// 2x `ref mut`.
|
||||
@ -767,10 +767,10 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
||||
conflicts_mut_ref.push(Conflict::Ref { span, name })
|
||||
}
|
||||
},
|
||||
BindingMode::ByValue if is_binding_by_move(ty) => {
|
||||
ByRef::No if is_binding_by_move(ty) => {
|
||||
conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
|
||||
}
|
||||
BindingMode::ByValue => {} // `ref mut?` + by-copy is fine.
|
||||
ByRef::No => {} // `ref mut?` + by-copy is fine.
|
||||
}
|
||||
});
|
||||
|
||||
@ -813,8 +813,7 @@ fn check_for_bindings_named_same_as_variants(
|
||||
) {
|
||||
if let PatKind::Binding {
|
||||
name,
|
||||
mode: BindingMode::ByValue,
|
||||
mutability: Mutability::Not,
|
||||
mode: BindingAnnotation(ByRef::No, Mutability::Not),
|
||||
subpattern: None,
|
||||
ty,
|
||||
..
|
||||
|
@ -9,15 +9,14 @@ use crate::errors::*;
|
||||
use crate::thir::util::UserAnnotatedTyHelpers;
|
||||
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc_hir::RangeEnd;
|
||||
use rustc_hir::{self as hir, RangeEnd};
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::mir::interpret::{ErrorHandled, GlobalId, LitToConstError, LitToConstInput};
|
||||
use rustc_middle::mir::{self, BorrowKind, Const, Mutability};
|
||||
use rustc_middle::mir::{self, Const};
|
||||
use rustc_middle::thir::{
|
||||
Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
|
||||
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
|
||||
};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
|
||||
@ -281,26 +280,16 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
span = span.with_hi(ident_span.hi());
|
||||
}
|
||||
|
||||
let bm = *self
|
||||
let mode = *self
|
||||
.typeck_results
|
||||
.pat_binding_modes()
|
||||
.get(pat.hir_id)
|
||||
.expect("missing binding mode");
|
||||
let (mutability, mode) = match bm {
|
||||
ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
|
||||
ty::BindByReference(hir::Mutability::Mut) => (
|
||||
Mutability::Not,
|
||||
BindingMode::ByRef(BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|
||||
),
|
||||
ty::BindByReference(hir::Mutability::Not) => {
|
||||
(Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))
|
||||
}
|
||||
};
|
||||
|
||||
// A ref x pattern is the same node used for x, and as such it has
|
||||
// x's type, which is &T, where we want T (the type being matched).
|
||||
let var_ty = ty;
|
||||
if let ty::BindByReference(_) = bm {
|
||||
if let hir::ByRef::Yes(_) = mode.0 {
|
||||
if let ty::Ref(_, rty, _) = ty.kind() {
|
||||
ty = *rty;
|
||||
} else {
|
||||
@ -309,7 +298,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
PatKind::Binding {
|
||||
mutability,
|
||||
mode,
|
||||
name: ident.name,
|
||||
var: LocalVarId(id),
|
||||
|
@ -635,9 +635,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
||||
self.print_pat(subpattern, depth_lvl + 3);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
PatKind::Binding { mutability, name, mode, var, ty, subpattern, is_primary } => {
|
||||
PatKind::Binding { name, mode, var, ty, subpattern, is_primary } => {
|
||||
print_indented!(self, "Binding {", depth_lvl + 1);
|
||||
print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 2);
|
||||
print_indented!(self, format!("name: {:?}", name), depth_lvl + 2);
|
||||
print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2);
|
||||
print_indented!(self, format!("var: {:?}", var), depth_lvl + 2);
|
||||
|
@ -1226,7 +1226,7 @@ fn create_coroutine_drop_shim<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
transform: &TransformVisitor<'tcx>,
|
||||
coroutine_ty: Ty<'tcx>,
|
||||
body: &mut Body<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
drop_clean: BasicBlock,
|
||||
) -> Body<'tcx> {
|
||||
let mut body = body.clone();
|
||||
|
@ -123,8 +123,11 @@ fn create_mappings<'tcx>(
|
||||
let body_span = hir_info.body_span;
|
||||
|
||||
let source_file = source_map.lookup_source_file(body_span.lo());
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let file_name = Symbol::intern(&source_file.name.for_codegen(tcx.sess).to_string_lossy());
|
||||
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
let file_name = Symbol::intern(
|
||||
&source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
|
||||
);
|
||||
|
||||
let term_for_bcb = |bcb| {
|
||||
coverage_counters
|
||||
|
@ -84,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
|
||||
///
|
||||
/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
|
||||
/// to the return place along all possible paths through the control-flow graph.
|
||||
fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
|
||||
fn local_eligible_for_nrvo(body: &mir::Body<'_>) -> Option<Local> {
|
||||
if IsReturnPlaceRead::run(body) {
|
||||
return None;
|
||||
}
|
||||
@ -118,10 +118,7 @@ fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
|
||||
copied_to_return_place
|
||||
}
|
||||
|
||||
fn find_local_assigned_to_return_place(
|
||||
start: BasicBlock,
|
||||
body: &mut mir::Body<'_>,
|
||||
) -> Option<Local> {
|
||||
fn find_local_assigned_to_return_place(start: BasicBlock, body: &mir::Body<'_>) -> Option<Local> {
|
||||
let mut block = start;
|
||||
let mut seen = BitSet::new_empty(body.basic_blocks.len());
|
||||
|
||||
|
@ -655,9 +655,6 @@ parse_question_mark_in_type = invalid `?` in type
|
||||
parse_recover_import_as_use = expected item, found {$token_name}
|
||||
.suggestion = items are imported using the `use` keyword
|
||||
|
||||
parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
|
||||
.suggestion = try switching the order
|
||||
|
||||
parse_remove_let = expected pattern, found `let`
|
||||
.suggestion = remove the unnecessary `let` keyword
|
||||
|
||||
|
@ -2364,14 +2364,6 @@ pub(crate) struct UnexpectedLifetimeInPattern {
|
||||
pub symbol: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_ref_mut_order_incorrect)]
|
||||
pub(crate) struct RefMutOrderIncorrect {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "ref mut", applicability = "machine-applicable")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum InvalidMutInPattern {
|
||||
#[diag(parse_mut_on_nested_ident_pattern)]
|
||||
|
@ -24,12 +24,11 @@ use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
||||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::AttrId;
|
||||
use rustc_ast::CoroutineKind;
|
||||
use rustc_ast::DUMMY_NODE_ID;
|
||||
use rustc_ast::{self as ast, AnonConst, Const, DelimArgs, Extern};
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, Expr, ExprKind, Mutability, StrLit};
|
||||
use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind};
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
|
||||
Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, StrLit, Unsafe, Visibility,
|
||||
VisibilityKind, DUMMY_NODE_ID,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::PResult;
|
||||
@ -1273,6 +1272,11 @@ impl<'a> Parser<'a> {
|
||||
if self.eat_keyword(kw::Mut) { Mutability::Mut } else { Mutability::Not }
|
||||
}
|
||||
|
||||
/// Parses reference binding mode (`ref`, `ref mut`, or nothing).
|
||||
fn parse_byref(&mut self) -> ByRef {
|
||||
if self.eat_keyword(kw::Ref) { ByRef::Yes(self.parse_mutability()) } else { ByRef::No }
|
||||
}
|
||||
|
||||
/// Possibly parses mutability (`const` or `mut`).
|
||||
fn parse_const_or_mut(&mut self) -> Option<Mutability> {
|
||||
if self.eat_keyword(kw::Mut) {
|
||||
|
@ -4,11 +4,11 @@ use crate::errors::{
|
||||
DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
|
||||
ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
|
||||
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
|
||||
PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
|
||||
SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
|
||||
TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
|
||||
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
|
||||
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern,
|
||||
PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder,
|
||||
TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
|
||||
UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat,
|
||||
UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam,
|
||||
UnexpectedVertVertInPattern,
|
||||
};
|
||||
use crate::parser::expr::could_be_unclosed_char_literal;
|
||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||
@ -476,7 +476,7 @@ impl<'a> Parser<'a> {
|
||||
// Parse `_`
|
||||
PatKind::Wild
|
||||
} else if self.eat_keyword(kw::Mut) {
|
||||
self.parse_pat_ident_mut(syntax_loc)?
|
||||
self.parse_pat_ident_mut()?
|
||||
} else if self.eat_keyword(kw::Ref) {
|
||||
if self.check_keyword(kw::Box) {
|
||||
// Suggest `box ref`.
|
||||
@ -486,7 +486,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
// Parse ref ident @ pat / ref mut ident @ pat
|
||||
let mutbl = self.parse_mutability();
|
||||
self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)?
|
||||
self.parse_pat_ident(BindingAnnotation(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)?
|
||||
} else if self.eat_keyword(kw::Box) {
|
||||
self.parse_pat_box()?
|
||||
} else if self.check_inline_const(0) {
|
||||
@ -746,13 +746,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a mutable binding with the `mut` token already eaten.
|
||||
fn parse_pat_ident_mut(&mut self, syntax_loc: Option<PatternLocation>) -> PResult<'a, PatKind> {
|
||||
fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> {
|
||||
let mut_span = self.prev_token.span;
|
||||
|
||||
if self.eat_keyword(kw::Ref) {
|
||||
self.dcx().emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) });
|
||||
return self.parse_pat_ident(BindingAnnotation::REF_MUT, syntax_loc);
|
||||
}
|
||||
self.recover_additional_muts();
|
||||
|
||||
let byref = self.parse_byref();
|
||||
|
||||
self.recover_additional_muts();
|
||||
|
||||
@ -767,10 +766,12 @@ impl<'a> Parser<'a> {
|
||||
let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?;
|
||||
|
||||
// If we don't have `mut $ident (@ pat)?`, error.
|
||||
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
|
||||
if let PatKind::Ident(BindingAnnotation(br @ ByRef::No, m @ Mutability::Not), ..) =
|
||||
&mut pat.kind
|
||||
{
|
||||
// Don't recurse into the subpattern.
|
||||
// `mut` on the outer binding doesn't affect the inner bindings.
|
||||
*br = byref;
|
||||
*m = Mutability::Mut;
|
||||
} else {
|
||||
// Add `mut` to any binding in the parsed pattern.
|
||||
@ -778,6 +779,10 @@ impl<'a> Parser<'a> {
|
||||
self.ban_mut_general_pat(mut_span, &pat, changed_any_binding);
|
||||
}
|
||||
|
||||
if matches!(pat.kind, PatKind::Ident(BindingAnnotation(ByRef::Yes(_), Mutability::Mut), ..))
|
||||
{
|
||||
self.psess.gated_spans.gate(sym::mut_ref, pat.span);
|
||||
}
|
||||
Ok(pat.into_inner().kind)
|
||||
}
|
||||
|
||||
@ -1390,16 +1395,12 @@ impl<'a> Parser<'a> {
|
||||
// Parsing a pattern of the form `(box) (ref) (mut) fieldname`.
|
||||
let is_box = self.eat_keyword(kw::Box);
|
||||
let boxed_span = self.token.span;
|
||||
let is_ref = self.eat_keyword(kw::Ref);
|
||||
let is_mut = self.eat_keyword(kw::Mut);
|
||||
let mutability = self.parse_mutability();
|
||||
let by_ref = self.parse_byref();
|
||||
|
||||
let fieldname = self.parse_field_name()?;
|
||||
hi = self.prev_token.span;
|
||||
|
||||
let mutability = match is_mut {
|
||||
false => Mutability::Not,
|
||||
true => Mutability::Mut,
|
||||
};
|
||||
let ann = BindingAnnotation(ByRef::from(is_ref), mutability);
|
||||
let ann = BindingAnnotation(by_ref, mutability);
|
||||
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
|
||||
let subpat =
|
||||
if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
|
||||
|
@ -7,6 +7,7 @@ use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{sigpipe, CrateType, EntryFnType};
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
@ -165,10 +166,14 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
|
||||
|
||||
// There is no main function.
|
||||
let mut has_filename = true;
|
||||
let filename = tcx.sess.local_crate_source_file().unwrap_or_else(|| {
|
||||
has_filename = false;
|
||||
Default::default()
|
||||
});
|
||||
let filename = tcx
|
||||
.sess
|
||||
.local_crate_source_file()
|
||||
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DIAGNOSTICS).to_path_buf())
|
||||
.unwrap_or_else(|| {
|
||||
has_filename = false;
|
||||
Default::default()
|
||||
});
|
||||
let main_def_opt = tcx.resolutions(()).main_def;
|
||||
let code = E0601;
|
||||
let add_teach_note = tcx.sess.teach(code);
|
||||
|
@ -990,22 +990,12 @@ bitflags::bitflags! {
|
||||
const MACRO = 1 << 0;
|
||||
/// Apply remappings to printed compiler diagnostics
|
||||
const DIAGNOSTICS = 1 << 1;
|
||||
/// Apply remappings to debug information only when they are written to
|
||||
/// compiled executables or libraries, but not when they are in split
|
||||
/// debuginfo files
|
||||
const UNSPLIT_DEBUGINFO = 1 << 2;
|
||||
/// Apply remappings to debug information only when they are written to
|
||||
/// split debug information files, but not in compiled executables or
|
||||
/// libraries
|
||||
const SPLIT_DEBUGINFO = 1 << 3;
|
||||
/// Apply remappings to the paths pointing to split debug information
|
||||
/// files. Does nothing when these files are not generated.
|
||||
const SPLIT_DEBUGINFO_PATH = 1 << 4;
|
||||
/// Apply remappings to debug informations
|
||||
const DEBUGINFO = 1 << 3;
|
||||
|
||||
/// An alias for macro,unsplit-debuginfo,split-debuginfo-path. This
|
||||
/// ensures all paths in compiled executables or libraries are remapped
|
||||
/// but not elsewhere.
|
||||
const OBJECT = Self::MACRO.bits() | Self::UNSPLIT_DEBUGINFO.bits() | Self::SPLIT_DEBUGINFO_PATH.bits();
|
||||
/// An alias for `macro` and `debuginfo`. This ensures all paths in compiled
|
||||
/// executables or libraries are remapped but not elsewhere.
|
||||
const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2010,7 +2000,7 @@ pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches
|
||||
}
|
||||
|
||||
fn check_error_format_stability(
|
||||
early_dcx: &mut EarlyDiagCtxt,
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
unstable_opts: &UnstableOptions,
|
||||
error_format: ErrorOutputType,
|
||||
) {
|
||||
@ -2108,7 +2098,7 @@ fn should_override_cgus_and_disable_thinlto(
|
||||
fn collect_print_requests(
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
cg: &mut CodegenOptions,
|
||||
unstable_opts: &mut UnstableOptions,
|
||||
unstable_opts: &UnstableOptions,
|
||||
matches: &getopts::Matches,
|
||||
) -> Vec<PrintRequest> {
|
||||
let mut prints = Vec::<PrintRequest>::new();
|
||||
@ -2574,7 +2564,7 @@ fn parse_remap_path_prefix(
|
||||
}
|
||||
|
||||
fn parse_logical_env(
|
||||
early_dcx: &mut EarlyDiagCtxt,
|
||||
early_dcx: &EarlyDiagCtxt,
|
||||
matches: &getopts::Matches,
|
||||
) -> FxIndexMap<String, String> {
|
||||
let mut vars = FxIndexMap::default();
|
||||
@ -2732,6 +2722,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||
}
|
||||
|
||||
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
|
||||
// FIXME: this is only mutation of UnstableOptions here, move into
|
||||
// UnstableOptions::build?
|
||||
unstable_opts.graphviz_font = graphviz_font;
|
||||
}
|
||||
|
||||
@ -2781,7 +2773,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||
));
|
||||
}
|
||||
|
||||
let prints = collect_print_requests(early_dcx, &mut cg, &mut unstable_opts, matches);
|
||||
let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
|
||||
|
||||
let cg = cg;
|
||||
|
||||
@ -2852,13 +2844,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
|
||||
});
|
||||
|
||||
let remap = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
let (path, remapped) = remap.map_prefix(&working_dir);
|
||||
let working_dir = if remapped {
|
||||
RealFileName::Remapped { virtual_name: path.into_owned(), local_path: Some(working_dir) }
|
||||
} else {
|
||||
RealFileName::LocalPath(path.into_owned())
|
||||
};
|
||||
let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
let working_dir = file_mapping.to_real_filename(&working_dir);
|
||||
|
||||
let verbose = matches.opt_present("verbose") || unstable_opts.verbose_internals;
|
||||
|
||||
|
@ -433,7 +433,8 @@ mod desc {
|
||||
"a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`";
|
||||
pub const parse_proc_macro_execution_strategy: &str =
|
||||
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
|
||||
pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
|
||||
pub const parse_remap_path_scope: &str =
|
||||
"comma separated list of scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`";
|
||||
pub const parse_inlining_threshold: &str =
|
||||
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
|
||||
pub const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
|
||||
@ -1156,9 +1157,7 @@ mod parse {
|
||||
*slot |= match s {
|
||||
"macro" => RemapPathScopeComponents::MACRO,
|
||||
"diagnostics" => RemapPathScopeComponents::DIAGNOSTICS,
|
||||
"unsplit-debuginfo" => RemapPathScopeComponents::UNSPLIT_DEBUGINFO,
|
||||
"split-debuginfo" => RemapPathScopeComponents::SPLIT_DEBUGINFO,
|
||||
"split-debuginfo-path" => RemapPathScopeComponents::SPLIT_DEBUGINFO_PATH,
|
||||
"debuginfo" => RemapPathScopeComponents::DEBUGINFO,
|
||||
"object" => RemapPathScopeComponents::OBJECT,
|
||||
"all" => RemapPathScopeComponents::all(),
|
||||
_ => return false,
|
||||
|
@ -29,6 +29,7 @@ use rustc_macros::HashStable_Generic;
|
||||
pub use rustc_span::def_id::StableCrateId;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{FileLoader, FilePathMapping, RealFileLoader, SourceMap};
|
||||
use rustc_span::{FileNameDisplayPreference, RealFileName};
|
||||
use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
|
||||
@ -250,13 +251,8 @@ impl Session {
|
||||
self.miri_unleashed_features.lock().push((span, feature_gate));
|
||||
}
|
||||
|
||||
pub fn local_crate_source_file(&self) -> Option<PathBuf> {
|
||||
let path = self.io.input.opt_path()?;
|
||||
if self.should_prefer_remapped_for_codegen() {
|
||||
Some(self.opts.file_path_mapping().map_prefix(path).0.into_owned())
|
||||
} else {
|
||||
Some(path.to_path_buf())
|
||||
}
|
||||
pub fn local_crate_source_file(&self) -> Option<RealFileName> {
|
||||
Some(self.source_map().path_mapping().to_real_filename(self.io.input.opt_path()?))
|
||||
}
|
||||
|
||||
fn check_miri_unleashed_features(&self) -> Option<ErrorGuaranteed> {
|
||||
@ -886,38 +882,19 @@ impl Session {
|
||||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_codegen(&self) -> bool {
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed => true,
|
||||
SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
let remap_path_scopes = &self.opts.unstable_opts.remap_path_scope;
|
||||
let mut prefer_remapped = false;
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::UNSPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= !has_split_debuginfo;
|
||||
pub fn filename_display_preference(
|
||||
&self,
|
||||
scope: RemapPathScopeComponents,
|
||||
) -> FileNameDisplayPreference {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to `Session::filename_display_preference`"
|
||||
);
|
||||
if self.opts.unstable_opts.remap_path_scope.contains(scope) {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
}
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= has_split_debuginfo;
|
||||
}
|
||||
|
||||
prefer_remapped
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_split_debuginfo_paths(&self) -> bool {
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed | SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
self.opts
|
||||
.unstable_opts
|
||||
.remap_path_scope
|
||||
.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO_PATH)
|
||||
&& has_split_debuginfo
|
||||
}
|
||||
}
|
||||
|
||||
@ -1469,12 +1446,8 @@ pub trait RemapFileNameExt {
|
||||
|
||||
/// Returns a possibly remapped filename based on the passed scope and remap cli options.
|
||||
///
|
||||
/// One and only one scope should be passed to this method. For anything related to
|
||||
/// "codegen" see the [`RemapFileNameExt::for_codegen`] method.
|
||||
/// One and only one scope should be passed to this method, it will panic otherwise.
|
||||
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_>;
|
||||
|
||||
/// Return a possibly remapped filename, to be used in "codegen" related parts.
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_>;
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::FileName {
|
||||
@ -1491,14 +1464,6 @@ impl RemapFileNameExt for rustc_span::FileName {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.prefer_remapped_unconditionaly()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::RealFileName {
|
||||
@ -1515,12 +1480,4 @@ impl RemapFileNameExt for rustc_span::RealFileName {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
||||
|
||||
const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
|
||||
|
||||
let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
|
||||
let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string());
|
||||
|
||||
let mut result = Vec::new();
|
||||
let mut excluded_cargo_defaults = false;
|
||||
|
@ -420,7 +420,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
let tcx = tables.tcx;
|
||||
let args = args.internal(&mut *tables, tcx);
|
||||
let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx));
|
||||
def_ty.instantiate(tables.tcx, args).stable(&mut *tables)
|
||||
tables
|
||||
.tcx
|
||||
.instantiate_and_normalize_erasing_regions(args, ty::ParamEnv::reveal_all(), def_ty)
|
||||
.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn const_pretty(&self, cnst: &stable_mir::ty::Const) -> String {
|
||||
|
@ -271,6 +271,18 @@ impl RealFileName {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the path remmapped or not depending on the [`FileNameDisplayPreference`].
|
||||
///
|
||||
/// For the purpose of this function, local and short preference are equal.
|
||||
pub fn to_path(&self, display_pref: FileNameDisplayPreference) -> &Path {
|
||||
match display_pref {
|
||||
FileNameDisplayPreference::Local | FileNameDisplayPreference::Short => {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
FileNameDisplayPreference::Remapped => self.remapped_path_if_available(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> {
|
||||
match display_pref {
|
||||
FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(),
|
||||
|
@ -1129,6 +1129,21 @@ impl FilePathMapping {
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies any path prefix substitution as defined by the mapping.
|
||||
/// The return value is the local path with a "virtual path" representing the remapped
|
||||
/// part if any remapping was performed.
|
||||
pub fn to_real_filename<'a>(&self, local_path: impl Into<Cow<'a, Path>>) -> RealFileName {
|
||||
let local_path = local_path.into();
|
||||
if let (remapped_path, true) = self.map_prefix(&*local_path) {
|
||||
RealFileName::Remapped {
|
||||
virtual_name: remapped_path.into_owned(),
|
||||
local_path: Some(local_path.into_owned()),
|
||||
}
|
||||
} else {
|
||||
RealFileName::LocalPath(local_path.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand a relative path to an absolute path with remapping taken into account.
|
||||
/// Use this when absolute paths are required (e.g. debuginfo or crate metadata).
|
||||
///
|
||||
|
@ -531,8 +531,15 @@ symbols! {
|
||||
cmp,
|
||||
cmp_max,
|
||||
cmp_min,
|
||||
cmp_ord_max,
|
||||
cmp_ord_min,
|
||||
cmp_partialeq_eq,
|
||||
cmp_partialeq_ne,
|
||||
cmp_partialord_cmp,
|
||||
cmp_partialord_ge,
|
||||
cmp_partialord_gt,
|
||||
cmp_partialord_le,
|
||||
cmp_partialord_lt,
|
||||
cmpxchg16b_target_feature,
|
||||
cmse_nonsecure_entry,
|
||||
coerce_unsized,
|
||||
@ -1185,6 +1192,7 @@ symbols! {
|
||||
multiple_supertrait_upcastable,
|
||||
must_not_suspend,
|
||||
must_use,
|
||||
mut_ref,
|
||||
naked,
|
||||
naked_functions,
|
||||
name,
|
||||
|
@ -13,9 +13,20 @@ bitflags! {
|
||||
/// Options for typeid_for_fnabi.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct TypeIdOptions: u32 {
|
||||
/// Generalizes pointers for compatibility with Clang
|
||||
/// `-fsanitize-cfi-icall-generalize-pointers` option for cross-language LLVM CFI and KCFI
|
||||
/// support.
|
||||
const GENERALIZE_POINTERS = 1;
|
||||
/// Generalizes repr(C) user-defined type for extern function types with the "C" calling
|
||||
/// convention (or extern types) for cross-language LLVM CFI and KCFI support.
|
||||
const GENERALIZE_REPR_C = 2;
|
||||
/// Normalizes integers for compatibility with Clang
|
||||
/// `-fsanitize-cfi-icall-experimental-normalize-integers` option for cross-language LLVM
|
||||
/// CFI and KCFI support.
|
||||
const NORMALIZE_INTEGERS = 4;
|
||||
/// Do not perform self type erasure for attaching a secondary type id to methods with their
|
||||
/// concrete self so they can be used as function pointers.
|
||||
const NO_SELF_TYPE_ERASURE = 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1144,7 +1144,8 @@ pub fn typeid_for_instance<'tcx>(
|
||||
instance.args = strip_receiver_auto(tcx, instance.args);
|
||||
}
|
||||
|
||||
if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
|
||||
if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE)
|
||||
&& let Some(impl_id) = tcx.impl_of_method(instance.def_id())
|
||||
&& let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
|
||||
{
|
||||
let impl_method = tcx.associated_item(instance.def_id());
|
||||
|
@ -4931,7 +4931,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
|
||||
let hir::WherePredicate::BoundPredicate(pred) = pred else {
|
||||
continue;
|
||||
};
|
||||
let mut bounds = pred.bounds.iter().peekable();
|
||||
let mut bounds = pred.bounds.iter();
|
||||
while let Some(bound) = bounds.next() {
|
||||
let Some(trait_ref) = bound.trait_ref() else {
|
||||
continue;
|
||||
|
@ -508,7 +508,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
||||
/// because it contains `[type error]`. Yuck! (See issue #29857 for
|
||||
/// one case where this arose.)
|
||||
fn normalize_to_error<'a, 'tcx>(
|
||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||
selcx: &SelectionContext<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
projection_ty: ty::AliasTy<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
|
@ -239,10 +239,10 @@ fn fulfill_implication<'tcx>(
|
||||
|
||||
let source_trait = ImplSubject::Trait(source_trait_ref);
|
||||
|
||||
let selcx = &mut SelectionContext::new(infcx);
|
||||
let selcx = SelectionContext::new(infcx);
|
||||
let target_args = infcx.fresh_args_for_item(DUMMY_SP, target_impl);
|
||||
let (target_trait, obligations) =
|
||||
util::impl_subject_and_oblig(selcx, param_env, target_impl, target_args, error_cause);
|
||||
util::impl_subject_and_oblig(&selcx, param_env, target_impl, target_args, error_cause);
|
||||
|
||||
// do the impls unify? If not, no specialization.
|
||||
let Ok(InferOk { obligations: more_obligations, .. }) = infcx
|
||||
|
@ -198,7 +198,7 @@ impl<'tcx> Children {
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
|
||||
fn iter_children(children: &Children) -> impl Iterator<Item = DefId> + '_ {
|
||||
let nonblanket = children.non_blanket_impls.iter().flat_map(|(_, v)| v.iter());
|
||||
children.blanket_impls.iter().chain(nonblanket).cloned()
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ impl Iterator for SupertraitDefIds<'_> {
|
||||
/// returning the resulting subject and all obligations that arise.
|
||||
/// The obligations are closed under normalization.
|
||||
pub fn impl_subject_and_oblig<'a, 'tcx>(
|
||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||
selcx: &SelectionContext<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
impl_def_id: DefId,
|
||||
impl_args: GenericArgsRef<'tcx>,
|
||||
|
@ -654,7 +654,7 @@ impl AdtDef {
|
||||
with(|cx| cx.def_ty(self.0))
|
||||
}
|
||||
|
||||
/// Retrieve the type of this Adt instantiating the type with the given arguments.
|
||||
/// Retrieve the type of this Adt by instantiating and normalizing it with the given arguments.
|
||||
///
|
||||
/// This will assume the type can be instantiated with these arguments.
|
||||
pub fn ty_with_args(&self, args: &GenericArgs) -> Ty {
|
||||
@ -733,7 +733,7 @@ pub struct FieldDef {
|
||||
}
|
||||
|
||||
impl FieldDef {
|
||||
/// Retrieve the type of this field instantiating the type with the given arguments.
|
||||
/// Retrieve the type of this field instantiating and normalizing it with the given arguments.
|
||||
///
|
||||
/// This will assume the type can be instantiated with these arguments.
|
||||
pub fn ty_with_args(&self, args: &GenericArgs) -> Ty {
|
||||
|
@ -2087,7 +2087,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
// buffer without it being full emerge
|
||||
debug_assert!(self.is_full());
|
||||
let old_cap = self.capacity();
|
||||
self.buf.reserve_for_push(old_cap);
|
||||
self.buf.grow_one();
|
||||
unsafe {
|
||||
self.handle_capacity_increase(old_cap);
|
||||
}
|
||||
|
@ -166,7 +166,6 @@
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(try_with_capacity)]
|
||||
#![feature(tuple_trait)]
|
||||
#![feature(unchecked_math)]
|
||||
#![feature(unicode_internals)]
|
||||
#![feature(unsize)]
|
||||
#![feature(utf8_chunks)]
|
||||
|
@ -345,12 +345,12 @@ impl<T, A: Allocator> RawVec<T, A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A specialized version of `reserve()` used only by the hot and
|
||||
/// oft-instantiated `Vec::push()`, which does its own capacity check.
|
||||
/// A specialized version of `self.reserve(len, 1)` which requires the
|
||||
/// caller to ensure `len == self.capacity()`.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline(never)]
|
||||
pub fn reserve_for_push(&mut self, len: usize) {
|
||||
if let Err(err) = self.grow_amortized(len, 1) {
|
||||
pub fn grow_one(&mut self) {
|
||||
if let Err(err) = self.grow_amortized(self.cap.0, 1) {
|
||||
handle_error(err);
|
||||
}
|
||||
}
|
||||
|
@ -1547,7 +1547,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
|
||||
// space for the new element
|
||||
if len == self.buf.capacity() {
|
||||
self.reserve(1);
|
||||
self.buf.grow_one();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@ -1967,7 +1967,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
// This will panic or abort if we would allocate > isize::MAX bytes
|
||||
// or if the length increment would overflow for zero-sized types.
|
||||
if self.len == self.buf.capacity() {
|
||||
self.buf.reserve_for_push(self.len);
|
||||
self.buf.grow_one();
|
||||
}
|
||||
unsafe {
|
||||
let end = self.as_mut_ptr().add(self.len);
|
||||
|
@ -42,7 +42,7 @@ use crate::ascii;
|
||||
use crate::error::Error;
|
||||
use crate::escape;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::iter::FusedIterator;
|
||||
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
|
||||
use crate::num::NonZero;
|
||||
|
||||
pub(crate) use self::methods::EscapeDebugExtArgs;
|
||||
@ -373,176 +373,229 @@ impl fmt::Display for EscapeDebug {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the lowercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_lowercase`]: char::to_lowercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToLowercase(CaseMappingIter);
|
||||
macro_rules! casemappingiter_impls {
|
||||
($(#[$attr:meta])* $ITER_NAME:ident) => {
|
||||
$(#[$attr])*
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct $ITER_NAME(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for ToLowercase {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for $ITER_NAME {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.0.fold(init, fold)
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
self.0.last()
|
||||
}
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
|
||||
self.0.advance_by(n)
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
// SAFETY: just forwarding requirements to caller
|
||||
unsafe { self.0.__iterator_get_unchecked(idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
|
||||
impl DoubleEndedIterator for $ITER_NAME {
|
||||
fn next_back(&mut self) -> Option<char> {
|
||||
self.0.next_back()
|
||||
}
|
||||
|
||||
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.0.rfold(init, rfold)
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
|
||||
self.0.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for $ITER_NAME {}
|
||||
|
||||
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
|
||||
impl ExactSizeIterator for $ITER_NAME {
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: forwards to inner `array::IntoIter`
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl TrustedLen for $ITER_NAME {}
|
||||
|
||||
// SAFETY: forwards to inner `array::IntoIter`
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "std_internals", issue = "none")]
|
||||
unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME {
|
||||
const MAY_HAVE_SIDE_EFFECT: bool = false;
|
||||
}
|
||||
|
||||
// SAFETY: this iter has no subtypes/supertypes
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "std_internals", issue = "none")]
|
||||
unsafe impl TrustedRandomAccess for $ITER_NAME {}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for $ITER_NAME {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
|
||||
impl DoubleEndedIterator for ToLowercase {
|
||||
fn next_back(&mut self) -> Option<char> {
|
||||
self.0.next_back()
|
||||
}
|
||||
casemappingiter_impls! {
|
||||
/// Returns an iterator that yields the lowercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_lowercase`]: char::to_lowercase
|
||||
ToLowercase
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for ToLowercase {}
|
||||
|
||||
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
|
||||
impl ExactSizeIterator for ToLowercase {}
|
||||
|
||||
/// Returns an iterator that yields the uppercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_uppercase`]: char::to_uppercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToUppercase(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for ToUppercase {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
casemappingiter_impls! {
|
||||
/// Returns an iterator that yields the uppercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_uppercase`]: char::to_uppercase
|
||||
ToUppercase
|
||||
}
|
||||
|
||||
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
|
||||
impl DoubleEndedIterator for ToUppercase {
|
||||
fn next_back(&mut self) -> Option<char> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for ToUppercase {}
|
||||
|
||||
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
|
||||
impl ExactSizeIterator for ToUppercase {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum CaseMappingIter {
|
||||
Three(char, char, char),
|
||||
Two(char, char),
|
||||
One(char),
|
||||
Zero,
|
||||
}
|
||||
struct CaseMappingIter(core::array::IntoIter<char, 3>);
|
||||
|
||||
impl CaseMappingIter {
|
||||
#[inline]
|
||||
fn new(chars: [char; 3]) -> CaseMappingIter {
|
||||
let mut iter = chars.into_iter();
|
||||
if chars[2] == '\0' {
|
||||
iter.next_back();
|
||||
if chars[1] == '\0' {
|
||||
CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
|
||||
} else {
|
||||
CaseMappingIter::Two(chars[0], chars[1])
|
||||
iter.next_back();
|
||||
|
||||
// Deliberately don't check `chars[0]`,
|
||||
// as '\0' lowercases to itself
|
||||
}
|
||||
} else {
|
||||
CaseMappingIter::Three(chars[0], chars[1], chars[2])
|
||||
}
|
||||
CaseMappingIter(iter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for CaseMappingIter {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match *self {
|
||||
CaseMappingIter::Three(a, b, c) => {
|
||||
*self = CaseMappingIter::Two(b, c);
|
||||
Some(a)
|
||||
}
|
||||
CaseMappingIter::Two(b, c) => {
|
||||
*self = CaseMappingIter::One(c);
|
||||
Some(b)
|
||||
}
|
||||
CaseMappingIter::One(c) => {
|
||||
*self = CaseMappingIter::Zero;
|
||||
Some(c)
|
||||
}
|
||||
CaseMappingIter::Zero => None,
|
||||
}
|
||||
self.0.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let size = match self {
|
||||
CaseMappingIter::Three(..) => 3,
|
||||
CaseMappingIter::Two(..) => 2,
|
||||
CaseMappingIter::One(_) => 1,
|
||||
CaseMappingIter::Zero => 0,
|
||||
};
|
||||
(size, Some(size))
|
||||
self.0.size_hint()
|
||||
}
|
||||
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.0.fold(init, fold)
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
self.0.last()
|
||||
}
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
|
||||
self.0.advance_by(n)
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
// SAFETY: just forwarding requirements to caller
|
||||
unsafe { self.0.__iterator_get_unchecked(idx) }
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for CaseMappingIter {
|
||||
fn next_back(&mut self) -> Option<char> {
|
||||
match *self {
|
||||
CaseMappingIter::Three(a, b, c) => {
|
||||
*self = CaseMappingIter::Two(a, b);
|
||||
Some(c)
|
||||
}
|
||||
CaseMappingIter::Two(b, c) => {
|
||||
*self = CaseMappingIter::One(b);
|
||||
Some(c)
|
||||
}
|
||||
CaseMappingIter::One(c) => {
|
||||
*self = CaseMappingIter::Zero;
|
||||
Some(c)
|
||||
}
|
||||
CaseMappingIter::Zero => None,
|
||||
}
|
||||
self.0.next_back()
|
||||
}
|
||||
|
||||
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.0.rfold(init, rfold)
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
|
||||
self.0.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for CaseMappingIter {
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for CaseMappingIter {}
|
||||
|
||||
// SAFETY: forwards to inner `array::IntoIter`
|
||||
unsafe impl TrustedLen for CaseMappingIter {}
|
||||
|
||||
// SAFETY: forwards to inner `array::IntoIter`
|
||||
unsafe impl TrustedRandomAccessNoCoerce for CaseMappingIter {
|
||||
const MAY_HAVE_SIDE_EFFECT: bool = false;
|
||||
}
|
||||
|
||||
// SAFETY: `CaseMappingIter` has no subtypes/supertypes
|
||||
unsafe impl TrustedRandomAccess for CaseMappingIter {}
|
||||
|
||||
impl fmt::Display for CaseMappingIter {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
CaseMappingIter::Three(a, b, c) => {
|
||||
f.write_char(a)?;
|
||||
f.write_char(b)?;
|
||||
f.write_char(c)
|
||||
}
|
||||
CaseMappingIter::Two(b, c) => {
|
||||
f.write_char(b)?;
|
||||
f.write_char(c)
|
||||
}
|
||||
CaseMappingIter::One(c) => f.write_char(c),
|
||||
CaseMappingIter::Zero => Ok(()),
|
||||
for c in self.0.clone() {
|
||||
f.write_char(c)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for ToLowercase {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for ToUppercase {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -848,6 +848,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
||||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_ord_max")]
|
||||
fn max(self, other: Self) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
@ -868,6 +869,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
||||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_ord_min")]
|
||||
fn min(self, other: Self) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
@ -1154,6 +1156,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_cmp")]
|
||||
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
|
||||
|
||||
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
|
||||
@ -1168,6 +1171,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_lt")]
|
||||
fn lt(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Less))
|
||||
}
|
||||
@ -1185,6 +1189,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_le")]
|
||||
fn le(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Less | Equal))
|
||||
}
|
||||
@ -1201,6 +1206,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_gt")]
|
||||
fn gt(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Greater))
|
||||
}
|
||||
@ -1218,6 +1224,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialord_ge")]
|
||||
fn ge(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Greater | Equal))
|
||||
}
|
||||
|
@ -2240,24 +2240,27 @@ extern "rust-intrinsic" {
|
||||
/// Returns the result of an unchecked addition, resulting in
|
||||
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_add` on the various
|
||||
/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns the result of an unchecked subtraction, resulting in
|
||||
/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
|
||||
/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns the result of an unchecked multiplication, resulting in
|
||||
/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
|
||||
///
|
||||
/// This intrinsic does not have a stable counterpart.
|
||||
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
|
||||
/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
|
||||
/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
|
||||
#[rustc_const_stable(feature = "unchecked_math", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_nounwind]
|
||||
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user