mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #130269 - Zalathar:rollup-coxzt2t, r=Zalathar
Rollup of 8 pull requests Successful merges: - #125060 (Expand documentation of PathBuf, discussing lack of sanitization) - #129367 (Fix default/minimum deployment target for Aarch64 simulator targets) - #130156 (Add test for S_OBJNAME & update test for LF_BUILDINFO cl and cmd) - #130160 (Fix `slice::first_mut` docs) - #130235 (Simplify some nested `if` statements) - #130250 (Fix `clippy::useless_conversion`) - #130252 (Properly report error on `const gen fn`) - #130256 (Re-run coverage tests if `coverage-dump` was modified) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
394c4060d2
@ -2602,12 +2602,12 @@ impl CoroutineKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_async(self) -> bool {
|
pub fn as_str(self) -> &'static str {
|
||||||
matches!(self, CoroutineKind::Async { .. })
|
match self {
|
||||||
}
|
CoroutineKind::Async { .. } => "async",
|
||||||
|
CoroutineKind::Gen { .. } => "gen",
|
||||||
pub fn is_gen(self) -> bool {
|
CoroutineKind::AsyncGen { .. } => "async gen",
|
||||||
matches!(self, CoroutineKind::Gen { .. })
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn closure_id(self) -> NodeId {
|
pub fn closure_id(self) -> NodeId {
|
||||||
@ -3486,7 +3486,7 @@ impl From<ForeignItemKind> for ItemKind {
|
|||||||
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
|
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
|
||||||
match foreign_item_kind {
|
match foreign_item_kind {
|
||||||
ForeignItemKind::Static(box static_foreign_item) => {
|
ForeignItemKind::Static(box static_foreign_item) => {
|
||||||
ItemKind::Static(Box::new(static_foreign_item.into()))
|
ItemKind::Static(Box::new(static_foreign_item))
|
||||||
}
|
}
|
||||||
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
|
||||||
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
|
||||||
@ -3500,9 +3500,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
|
|||||||
|
|
||||||
fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
|
fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
|
||||||
Ok(match item_kind {
|
Ok(match item_kind {
|
||||||
ItemKind::Static(box static_item) => {
|
ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)),
|
||||||
ForeignItemKind::Static(Box::new(static_item.into()))
|
|
||||||
}
|
|
||||||
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
|
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
|
||||||
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
|
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
|
||||||
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
|
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
|
||||||
|
@ -45,18 +45,16 @@ pub fn entry_point_type(
|
|||||||
EntryPointType::Start
|
EntryPointType::Start
|
||||||
} else if attr::contains_name(attrs, sym::rustc_main) {
|
} else if attr::contains_name(attrs, sym::rustc_main) {
|
||||||
EntryPointType::RustcMainAttr
|
EntryPointType::RustcMainAttr
|
||||||
} else {
|
} else if let Some(name) = name
|
||||||
if let Some(name) = name
|
&& name == sym::main
|
||||||
&& name == sym::main
|
{
|
||||||
{
|
if at_root {
|
||||||
if at_root {
|
// This is a top-level function so it can be `main`.
|
||||||
// This is a top-level function so it can be `main`.
|
EntryPointType::MainNamed
|
||||||
EntryPointType::MainNamed
|
|
||||||
} else {
|
|
||||||
EntryPointType::OtherMain
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
EntryPointType::None
|
EntryPointType::OtherMain
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
EntryPointType::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,26 +78,24 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
|||||||
|
|
||||||
// Make sure that the DepNode of some node coincides with the HirId
|
// Make sure that the DepNode of some node coincides with the HirId
|
||||||
// owner of that node.
|
// owner of that node.
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) && hir_id.owner != self.owner {
|
||||||
if hir_id.owner != self.owner {
|
span_bug!(
|
||||||
span_bug!(
|
span,
|
||||||
span,
|
"inconsistent HirId at `{:?}` for `{:?}`: \
|
||||||
"inconsistent HirId at `{:?}` for `{:?}`: \
|
|
||||||
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
|
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
|
||||||
self.tcx.sess.source_map().span_to_diagnostic_string(span),
|
self.tcx.sess.source_map().span_to_diagnostic_string(span),
|
||||||
node,
|
node,
|
||||||
self.tcx
|
self.tcx
|
||||||
.definitions_untracked()
|
.definitions_untracked()
|
||||||
.def_path(self.owner.def_id)
|
.def_path(self.owner.def_id)
|
||||||
.to_string_no_crate_verbose(),
|
.to_string_no_crate_verbose(),
|
||||||
self.owner,
|
self.owner,
|
||||||
self.tcx
|
self.tcx
|
||||||
.definitions_untracked()
|
.definitions_untracked()
|
||||||
.def_path(hir_id.owner.def_id)
|
.def_path(hir_id.owner.def_id)
|
||||||
.to_string_no_crate_verbose(),
|
.to_string_no_crate_verbose(),
|
||||||
hir_id.owner,
|
hir_id.owner,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node };
|
self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node };
|
||||||
|
@ -628,13 +628,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||||
_ => Const::No,
|
_ => Const::No,
|
||||||
}
|
}
|
||||||
|
} else if self.tcx.is_const_trait(def_id) {
|
||||||
|
// FIXME(effects) span
|
||||||
|
Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
|
||||||
} else {
|
} else {
|
||||||
if self.tcx.is_const_trait(def_id) {
|
Const::No
|
||||||
// FIXME(effects) span
|
|
||||||
Const::Yes(self.tcx.def_ident_span(def_id).unwrap())
|
|
||||||
} else {
|
|
||||||
Const::No
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Const::No
|
Const::No
|
||||||
|
@ -40,15 +40,15 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
|
|||||||
|
|
||||||
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
|
||||||
|
|
||||||
ast_passes_const_and_async = functions cannot be both `const` and `async`
|
|
||||||
.const = `const` because of this
|
|
||||||
.async = `async` because of this
|
|
||||||
.label = {""}
|
|
||||||
|
|
||||||
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
|
||||||
.const = `const` because of this
|
.const = `const` because of this
|
||||||
.variadic = C-variadic because of this
|
.variadic = C-variadic because of this
|
||||||
|
|
||||||
|
ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}`
|
||||||
|
.const = `const` because of this
|
||||||
|
.coroutine = `{$coroutine_kind}` because of this
|
||||||
|
.label = {""}
|
||||||
|
|
||||||
ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types
|
ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types
|
||||||
|
|
||||||
ast_passes_const_without_body =
|
ast_passes_const_without_body =
|
||||||
|
@ -447,13 +447,13 @@ impl<'a> AstValidator<'a> {
|
|||||||
fn check_item_safety(&self, span: Span, safety: Safety) {
|
fn check_item_safety(&self, span: Span, safety: Safety) {
|
||||||
match self.extern_mod_safety {
|
match self.extern_mod_safety {
|
||||||
Some(extern_safety) => {
|
Some(extern_safety) => {
|
||||||
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) {
|
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
|
||||||
if extern_safety == Safety::Default {
|
&& extern_safety == Safety::Default
|
||||||
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
{
|
||||||
item_span: span,
|
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||||
block: Some(self.current_extern_span().shrink_to_lo()),
|
item_span: span,
|
||||||
});
|
block: Some(self.current_extern_span().shrink_to_lo()),
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -1418,21 +1418,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
|
|
||||||
// Functions cannot both be `const async` or `const gen`
|
// Functions cannot both be `const async` or `const gen`
|
||||||
if let Some(&FnHeader {
|
if let Some(&FnHeader {
|
||||||
constness: Const::Yes(cspan),
|
constness: Const::Yes(const_span),
|
||||||
coroutine_kind: Some(coroutine_kind),
|
coroutine_kind: Some(coroutine_kind),
|
||||||
..
|
..
|
||||||
}) = fk.header()
|
}) = fk.header()
|
||||||
{
|
{
|
||||||
let aspan = match coroutine_kind {
|
self.dcx().emit_err(errors::ConstAndCoroutine {
|
||||||
CoroutineKind::Async { span: aspan, .. }
|
spans: vec![coroutine_kind.span(), const_span],
|
||||||
| CoroutineKind::Gen { span: aspan, .. }
|
const_span,
|
||||||
| CoroutineKind::AsyncGen { span: aspan, .. } => aspan,
|
coroutine_span: coroutine_kind.span(),
|
||||||
};
|
coroutine_kind: coroutine_kind.as_str(),
|
||||||
// FIXME(gen_blocks): Report a different error for `const gen`
|
|
||||||
self.dcx().emit_err(errors::ConstAndAsync {
|
|
||||||
spans: vec![cspan, aspan],
|
|
||||||
cspan,
|
|
||||||
aspan,
|
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -657,16 +657,17 @@ pub(crate) enum TildeConstReason {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_const_and_async)]
|
#[diag(ast_passes_const_and_coroutine)]
|
||||||
pub(crate) struct ConstAndAsync {
|
pub(crate) struct ConstAndCoroutine {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub spans: Vec<Span>,
|
pub spans: Vec<Span>,
|
||||||
#[label(ast_passes_const)]
|
#[label(ast_passes_const)]
|
||||||
pub cspan: Span,
|
pub const_span: Span,
|
||||||
#[label(ast_passes_async)]
|
#[label(ast_passes_coroutine)]
|
||||||
pub aspan: Span,
|
pub coroutine_span: Span,
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub coroutine_kind: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -2574,33 +2574,31 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
|
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
|
||||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||||
if e.span.contains(self.capture_span) {
|
if e.span.contains(self.capture_span)
|
||||||
if let hir::ExprKind::Closure(&hir::Closure {
|
&& let hir::ExprKind::Closure(&hir::Closure {
|
||||||
kind: hir::ClosureKind::Closure,
|
kind: hir::ClosureKind::Closure,
|
||||||
body,
|
body,
|
||||||
fn_arg_span,
|
fn_arg_span,
|
||||||
fn_decl: hir::FnDecl { inputs, .. },
|
fn_decl: hir::FnDecl { inputs, .. },
|
||||||
..
|
..
|
||||||
}) = e.kind
|
}) = e.kind
|
||||||
&& let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
|
&& let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
|
||||||
{
|
{
|
||||||
self.suggest_arg = "this: &Self".to_string();
|
self.suggest_arg = "this: &Self".to_string();
|
||||||
if inputs.len() > 0 {
|
if inputs.len() > 0 {
|
||||||
self.suggest_arg.push_str(", ");
|
self.suggest_arg.push_str(", ");
|
||||||
}
|
|
||||||
self.in_closure = true;
|
|
||||||
self.closure_arg_span = fn_arg_span;
|
|
||||||
self.visit_expr(body);
|
|
||||||
self.in_closure = false;
|
|
||||||
}
|
}
|
||||||
|
self.in_closure = true;
|
||||||
|
self.closure_arg_span = fn_arg_span;
|
||||||
|
self.visit_expr(body);
|
||||||
|
self.in_closure = false;
|
||||||
}
|
}
|
||||||
if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e {
|
if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e
|
||||||
if let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
|
&& let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
|
||||||
&& seg.ident.name == kw::SelfLower
|
&& seg.ident.name == kw::SelfLower
|
||||||
&& self.in_closure
|
&& self.in_closure
|
||||||
{
|
{
|
||||||
self.closure_change_spans.push(e.span);
|
self.closure_change_spans.push(e.span);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hir::intravisit::walk_expr(self, e);
|
hir::intravisit::walk_expr(self, e);
|
||||||
}
|
}
|
||||||
@ -2609,8 +2607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||||||
if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } =
|
if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } =
|
||||||
local.pat
|
local.pat
|
||||||
&& let Some(init) = local.init
|
&& let Some(init) = local.init
|
||||||
{
|
&& let hir::Expr {
|
||||||
if let hir::Expr {
|
|
||||||
kind:
|
kind:
|
||||||
hir::ExprKind::Closure(&hir::Closure {
|
hir::ExprKind::Closure(&hir::Closure {
|
||||||
kind: hir::ClosureKind::Closure,
|
kind: hir::ClosureKind::Closure,
|
||||||
@ -2618,11 +2615,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||||||
}),
|
}),
|
||||||
..
|
..
|
||||||
} = init
|
} = init
|
||||||
&& init.span.contains(self.capture_span)
|
&& init.span.contains(self.capture_span)
|
||||||
{
|
{
|
||||||
self.closure_local_id = Some(*hir_id);
|
self.closure_local_id = Some(*hir_id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::intravisit::walk_local(self, local);
|
hir::intravisit::walk_local(self, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2069,12 +2069,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||||||
// no move out from an earlier location) then this is an attempt at initialization
|
// no move out from an earlier location) then this is an attempt at initialization
|
||||||
// of the union - we should error in that case.
|
// of the union - we should error in that case.
|
||||||
let tcx = this.infcx.tcx;
|
let tcx = this.infcx.tcx;
|
||||||
if base.ty(this.body(), tcx).ty.is_union() {
|
if base.ty(this.body(), tcx).ty.is_union()
|
||||||
if this.move_data.path_map[mpi].iter().any(|moi| {
|
&& this.move_data.path_map[mpi].iter().any(|moi| {
|
||||||
this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
|
this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
|
||||||
}) {
|
})
|
||||||
return;
|
{
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.report_use_of_moved_or_uninitialized(
|
this.report_use_of_moved_or_uninitialized(
|
||||||
|
@ -118,10 +118,8 @@ impl LivenessValues {
|
|||||||
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
|
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
|
||||||
if let Some(points) = &mut self.points {
|
if let Some(points) = &mut self.points {
|
||||||
points.insert(region, point);
|
points.insert(region, point);
|
||||||
} else {
|
} else if self.elements.point_in_range(point) {
|
||||||
if self.elements.point_in_range(point) {
|
self.live_regions.as_mut().unwrap().insert(region);
|
||||||
self.live_regions.as_mut().unwrap().insert(region);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, record the loans flowing into this region as live at the given point.
|
// When available, record the loans flowing into this region as live at the given point.
|
||||||
@ -137,10 +135,8 @@ impl LivenessValues {
|
|||||||
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
|
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
|
||||||
if let Some(this) = &mut self.points {
|
if let Some(this) = &mut self.points {
|
||||||
this.union_row(region, points);
|
this.union_row(region, points);
|
||||||
} else {
|
} else if points.iter().any(|point| self.elements.point_in_range(point)) {
|
||||||
if points.iter().any(|point| self.elements.point_in_range(point)) {
|
self.live_regions.as_mut().unwrap().insert(region);
|
||||||
self.live_regions.as_mut().unwrap().insert(region);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, record the loans flowing into this region as live at the given points.
|
// When available, record the loans flowing into this region as live at the given points.
|
||||||
|
@ -353,11 +353,11 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
|
|||||||
let location = self.cx.elements.to_location(drop_point);
|
let location = self.cx.elements.to_location(drop_point);
|
||||||
debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
|
debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
|
||||||
|
|
||||||
if self.cx.initialized_at_terminator(location.block, mpi) {
|
if self.cx.initialized_at_terminator(location.block, mpi)
|
||||||
if self.drop_live_at.insert(drop_point) {
|
&& self.drop_live_at.insert(drop_point)
|
||||||
self.drop_locations.push(location);
|
{
|
||||||
self.stack.push(drop_point);
|
self.drop_locations.push(location);
|
||||||
}
|
self.stack.push(drop_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,13 +235,11 @@ pub fn parse_asm_args<'a>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
args.named_args.insert(name, slot);
|
args.named_args.insert(name, slot);
|
||||||
} else {
|
} else if !args.named_args.is_empty() || !args.reg_args.is_empty() {
|
||||||
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
|
let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
|
||||||
let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
|
let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect();
|
||||||
let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect();
|
|
||||||
|
|
||||||
dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
|
dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,11 +92,9 @@ fn prepare_lto(
|
|||||||
dcx.emit_err(LtoDylib);
|
dcx.emit_err(LtoDylib);
|
||||||
return Err(FatalError);
|
return Err(FatalError);
|
||||||
}
|
}
|
||||||
} else if *crate_type == CrateType::ProcMacro {
|
} else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto {
|
||||||
if !cgcx.opts.unstable_opts.dylib_lto {
|
dcx.emit_err(LtoProcMacro);
|
||||||
dcx.emit_err(LtoProcMacro);
|
return Err(FatalError);
|
||||||
return Err(FatalError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +281,10 @@ pub fn each_linked_rlib(
|
|||||||
let used_crate_source = &info.used_crate_source[&cnum];
|
let used_crate_source = &info.used_crate_source[&cnum];
|
||||||
if let Some((path, _)) = &used_crate_source.rlib {
|
if let Some((path, _)) = &used_crate_source.rlib {
|
||||||
f(cnum, path);
|
f(cnum, path);
|
||||||
|
} else if used_crate_source.rmeta.is_some() {
|
||||||
|
return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
||||||
} else {
|
} else {
|
||||||
if used_crate_source.rmeta.is_some() {
|
return Err(errors::LinkRlibError::NotFound { crate_name });
|
||||||
return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
|
||||||
} else {
|
|
||||||
return Err(errors::LinkRlibError::NotFound { crate_name });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -628,12 +626,10 @@ fn link_staticlib(
|
|||||||
let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
|
let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||||
if let Some((path, _)) = &used_crate_source.dylib {
|
if let Some((path, _)) = &used_crate_source.dylib {
|
||||||
all_rust_dylibs.push(&**path);
|
all_rust_dylibs.push(&**path);
|
||||||
|
} else if used_crate_source.rmeta.is_some() {
|
||||||
|
sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
||||||
} else {
|
} else {
|
||||||
if used_crate_source.rmeta.is_some() {
|
sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name });
|
||||||
sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
|
||||||
} else {
|
|
||||||
sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1972,10 +1968,8 @@ fn add_late_link_args(
|
|||||||
if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) {
|
if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) {
|
||||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
|
||||||
if let Some(args) = sess.target.late_link_args_static.get(&flavor) {
|
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some(args) = sess.target.late_link_args.get(&flavor) {
|
if let Some(args) = sess.target.late_link_args.get(&flavor) {
|
||||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||||
@ -2635,10 +2629,8 @@ fn add_native_libs_from_crate(
|
|||||||
if link_static {
|
if link_static {
|
||||||
cmd.link_staticlib_by_name(name, verbatim, false);
|
cmd.link_staticlib_by_name(name, verbatim, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else if link_dynamic {
|
||||||
if link_dynamic {
|
cmd.link_dylib_by_name(name, verbatim, true);
|
||||||
cmd.link_dylib_by_name(name, verbatim, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NativeLibKind::Framework { as_needed } => {
|
NativeLibKind::Framework { as_needed } => {
|
||||||
|
@ -791,14 +791,12 @@ impl<'a> Linker for GccLinker<'a> {
|
|||||||
self.link_arg("-exported_symbols_list").link_arg(path);
|
self.link_arg("-exported_symbols_list").link_arg(path);
|
||||||
} else if self.sess.target.is_like_solaris {
|
} else if self.sess.target.is_like_solaris {
|
||||||
self.link_arg("-M").link_arg(path);
|
self.link_arg("-M").link_arg(path);
|
||||||
|
} else if is_windows {
|
||||||
|
self.link_arg(path);
|
||||||
} else {
|
} else {
|
||||||
if is_windows {
|
let mut arg = OsString::from("--version-script=");
|
||||||
self.link_arg(path);
|
arg.push(path);
|
||||||
} else {
|
self.link_arg(arg).link_arg("--no-undefined-version");
|
||||||
let mut arg = OsString::from("--version-script=");
|
|
||||||
arg.push(path);
|
|
||||||
self.link_arg(arg).link_arg("--no-undefined-version");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,32 +617,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
// purpose functions as they wouldn't have the right target features
|
// purpose functions as they wouldn't have the right target features
|
||||||
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
||||||
// respected.
|
// respected.
|
||||||
if !codegen_fn_attrs.target_features.is_empty() {
|
if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always
|
||||||
if codegen_fn_attrs.inline == InlineAttr::Always {
|
{
|
||||||
if let Some(span) = inline_span {
|
if let Some(span) = inline_span {
|
||||||
tcx.dcx().span_err(
|
tcx.dcx().span_err(
|
||||||
span,
|
span,
|
||||||
"cannot use `#[inline(always)]` with \
|
"cannot use `#[inline(always)]` with \
|
||||||
`#[target_feature]`",
|
`#[target_feature]`",
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !codegen_fn_attrs.no_sanitize.is_empty() {
|
if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
|
||||||
if codegen_fn_attrs.inline == InlineAttr::Always {
|
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
|
||||||
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
|
let hir_id = tcx.local_def_id_to_hir_id(did);
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(did);
|
tcx.node_span_lint(
|
||||||
tcx.node_span_lint(
|
lint::builtin::INLINE_NO_SANITIZE,
|
||||||
lint::builtin::INLINE_NO_SANITIZE,
|
hir_id,
|
||||||
hir_id,
|
no_sanitize_span,
|
||||||
no_sanitize_span,
|
|lint| {
|
||||||
|lint| {
|
lint.primary_message("`no_sanitize` will have no effect after inlining");
|
||||||
lint.primary_message("`no_sanitize` will have no effect after inlining");
|
lint.span_note(inline_span, "inlining requested here");
|
||||||
lint.span_note(inline_span, "inlining requested here");
|
},
|
||||||
},
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,15 +236,13 @@ fn push_debuginfo_type_name<'tcx>(
|
|||||||
let has_enclosing_parens = if cpp_like_debuginfo {
|
let has_enclosing_parens = if cpp_like_debuginfo {
|
||||||
output.push_str("dyn$<");
|
output.push_str("dyn$<");
|
||||||
false
|
false
|
||||||
|
} else if trait_data.len() > 1 && auto_traits.len() != 0 {
|
||||||
|
// We need enclosing parens because there is more than one trait
|
||||||
|
output.push_str("(dyn ");
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
if trait_data.len() > 1 && auto_traits.len() != 0 {
|
output.push_str("dyn ");
|
||||||
// We need enclosing parens because there is more than one trait
|
false
|
||||||
output.push_str("(dyn ");
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
output.push_str("dyn ");
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(principal) = trait_data.principal() {
|
if let Some(principal) = trait_data.principal() {
|
||||||
|
@ -75,12 +75,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
|
|||||||
|
|
||||||
// This can't use `init_stack_frame` since `body` is not a function,
|
// This can't use `init_stack_frame` since `body` is not a function,
|
||||||
// so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
|
// so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
|
||||||
ecx.push_stack_frame_raw(
|
ecx.push_stack_frame_raw(cid.instance, body, &ret, StackPopCleanup::Root { cleanup: false })?;
|
||||||
cid.instance,
|
|
||||||
body,
|
|
||||||
&ret.clone().into(),
|
|
||||||
StackPopCleanup::Root { cleanup: false },
|
|
||||||
)?;
|
|
||||||
ecx.storage_live_for_always_live_locals()?;
|
ecx.storage_live_for_always_live_locals()?;
|
||||||
|
|
||||||
// The main interpreter loop.
|
// The main interpreter loop.
|
||||||
|
@ -823,7 +823,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
(Abi::Rust, fn_abi),
|
(Abi::Rust, fn_abi),
|
||||||
&[FnArg::Copy(arg.into())],
|
&[FnArg::Copy(arg.into())],
|
||||||
false,
|
false,
|
||||||
&ret.into(),
|
&ret,
|
||||||
Some(target),
|
Some(target),
|
||||||
unwind,
|
unwind,
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ use rustc_span::Span;
|
|||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, instrument, trace};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
err_inval, throw_inval, throw_ub, throw_ub_custom, Frame, FrameInfo, GlobalId, InterpErrorInfo,
|
err_inval, throw_inval, throw_ub, throw_ub_custom, Frame, FrameInfo, GlobalId, InterpErrorInfo,
|
||||||
@ -315,6 +315,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
|
|
||||||
/// Check if the two things are equal in the current param_env, using an infctx to get proper
|
/// Check if the two things are equal in the current param_env, using an infctx to get proper
|
||||||
/// equality checks.
|
/// equality checks.
|
||||||
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
|
pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
|
||||||
where
|
where
|
||||||
T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
|
T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
|
||||||
@ -330,13 +331,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
// equate the two trait refs after normalization
|
// equate the two trait refs after normalization
|
||||||
let a = ocx.normalize(&cause, self.param_env, a);
|
let a = ocx.normalize(&cause, self.param_env, a);
|
||||||
let b = ocx.normalize(&cause, self.param_env, b);
|
let b = ocx.normalize(&cause, self.param_env, b);
|
||||||
if ocx.eq(&cause, self.param_env, a, b).is_ok() {
|
|
||||||
if ocx.select_all_or_error().is_empty() {
|
if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) {
|
||||||
// All good.
|
trace!(?terr);
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
let errors = ocx.select_all_or_error();
|
||||||
|
if !errors.is_empty() {
|
||||||
|
trace!(?errors);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All good.
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
||||||
|
@ -222,10 +222,8 @@ impl<'tcx> PrintExtra<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
|
pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
|
||||||
if ppm.needs_analysis() {
|
if ppm.needs_analysis() && ex.tcx().analysis(()).is_err() {
|
||||||
if ex.tcx().analysis(()).is_err() {
|
FatalError.raise();
|
||||||
FatalError.raise();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (src, src_name) = get_source(sess);
|
let (src, src_name) = get_source(sess);
|
||||||
|
@ -681,10 +681,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||||||
" ".repeat(expected_padding),
|
" ".repeat(expected_padding),
|
||||||
expected_label
|
expected_label
|
||||||
))];
|
))];
|
||||||
msg.extend(expected.0.into_iter());
|
msg.extend(expected.0);
|
||||||
msg.push(StringPart::normal(format!("`{expected_extra}\n")));
|
msg.push(StringPart::normal(format!("`{expected_extra}\n")));
|
||||||
msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
|
msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
|
||||||
msg.extend(found.0.into_iter());
|
msg.extend(found.0);
|
||||||
msg.push(StringPart::normal(format!("`{found_extra}")));
|
msg.push(StringPart::normal(format!("`{found_extra}")));
|
||||||
|
|
||||||
// For now, just attach these as notes.
|
// For now, just attach these as notes.
|
||||||
|
@ -1151,42 +1151,40 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
|
|||||||
"type has conflicting packed and align representation hints"
|
"type has conflicting packed and align representation hints"
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
} else {
|
} else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
|
||||||
if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
|
let mut err = struct_span_code_err!(
|
||||||
let mut err = struct_span_code_err!(
|
tcx.dcx(),
|
||||||
tcx.dcx(),
|
sp,
|
||||||
sp,
|
E0588,
|
||||||
E0588,
|
"packed type cannot transitively contain a `#[repr(align)]` type"
|
||||||
"packed type cannot transitively contain a `#[repr(align)]` type"
|
);
|
||||||
);
|
|
||||||
|
|
||||||
err.span_note(
|
err.span_note(
|
||||||
tcx.def_span(def_spans[0].0),
|
tcx.def_span(def_spans[0].0),
|
||||||
format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
|
format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if def_spans.len() > 2 {
|
if def_spans.len() > 2 {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for (adt_def, span) in def_spans.iter().skip(1).rev() {
|
for (adt_def, span) in def_spans.iter().skip(1).rev() {
|
||||||
let ident = tcx.item_name(*adt_def);
|
let ident = tcx.item_name(*adt_def);
|
||||||
err.span_note(
|
err.span_note(
|
||||||
*span,
|
*span,
|
||||||
if first {
|
if first {
|
||||||
format!(
|
format!(
|
||||||
"`{}` contains a field of type `{}`",
|
"`{}` contains a field of type `{}`",
|
||||||
tcx.type_of(def.did()).instantiate_identity(),
|
tcx.type_of(def.did()).instantiate_identity(),
|
||||||
ident
|
ident
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!("...which contains a field of type `{ident}`")
|
format!("...which contains a field of type `{ident}`")
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
first = false;
|
first = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,17 +186,15 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
|
|||||||
|
|
||||||
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
|
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
|
||||||
&& alloc.inner().provenance().ptrs().len() != 0
|
&& alloc.inner().provenance().ptrs().len() != 0
|
||||||
{
|
&& attrs
|
||||||
if attrs
|
|
||||||
.link_section
|
.link_section
|
||||||
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
|
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
let msg = "statics with a custom `#[link_section]` must be a \
|
let msg = "statics with a custom `#[link_section]` must be a \
|
||||||
simple list of bytes on the wasm target with no \
|
simple list of bytes on the wasm target with no \
|
||||||
extra levels of indirection such as references";
|
extra levels of indirection such as references";
|
||||||
tcx.dcx().span_err(tcx.def_span(id), msg);
|
tcx.dcx().span_err(tcx.def_span(id), msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,7 +1602,7 @@ fn check_fn_or_method<'tcx>(
|
|||||||
function: def_id,
|
function: def_id,
|
||||||
// Note that the `param_idx` of the output type is
|
// Note that the `param_idx` of the output type is
|
||||||
// one greater than the index of the last input type.
|
// one greater than the index of the last input type.
|
||||||
param_idx: idx.try_into().unwrap(),
|
param_idx: idx,
|
||||||
}),
|
}),
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
@ -1611,7 +1611,7 @@ fn check_fn_or_method<'tcx>(
|
|||||||
for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
|
for (idx, ty) in sig.inputs_and_output.iter().enumerate() {
|
||||||
wfcx.register_wf_obligation(
|
wfcx.register_wf_obligation(
|
||||||
arg_span(idx),
|
arg_span(idx),
|
||||||
Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }),
|
Some(WellFormedLoc::Param { function: def_id, param_idx: idx }),
|
||||||
ty.into(),
|
ty.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -53,17 +53,15 @@ fn enforce_trait_manually_implementable(
|
|||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let impl_header_span = tcx.def_span(impl_def_id);
|
let impl_header_span = tcx.def_span(impl_def_id);
|
||||||
|
|
||||||
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) {
|
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls {
|
||||||
if !tcx.features().freeze_impls {
|
feature_err(
|
||||||
feature_err(
|
&tcx.sess,
|
||||||
&tcx.sess,
|
sym::freeze_impls,
|
||||||
sym::freeze_impls,
|
impl_header_span,
|
||||||
impl_header_span,
|
"explicit impls for the `Freeze` trait are not permitted",
|
||||||
"explicit impls for the `Freeze` trait are not permitted",
|
)
|
||||||
)
|
.with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
|
||||||
.with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
|
.emit();
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
|
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
|
||||||
|
@ -381,24 +381,22 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
mir_opaque_ty.ty
|
mir_opaque_ty.ty
|
||||||
|
} else if let Some(guar) = tables.tainted_by_errors {
|
||||||
|
// Some error in the owner fn prevented us from populating
|
||||||
|
// the `concrete_opaque_types` table.
|
||||||
|
Ty::new_error(tcx, guar)
|
||||||
} else {
|
} else {
|
||||||
if let Some(guar) = tables.tainted_by_errors {
|
// Fall back to the RPIT we inferred during HIR typeck
|
||||||
// Some error in the owner fn prevented us from populating
|
if let Some(hir_opaque_ty) = hir_opaque_ty {
|
||||||
// the `concrete_opaque_types` table.
|
hir_opaque_ty.ty
|
||||||
Ty::new_error(tcx, guar)
|
|
||||||
} else {
|
} else {
|
||||||
// Fall back to the RPIT we inferred during HIR typeck
|
// We failed to resolve the opaque type or it
|
||||||
if let Some(hir_opaque_ty) = hir_opaque_ty {
|
// resolves to itself. We interpret this as the
|
||||||
hir_opaque_ty.ty
|
// no values of the hidden type ever being constructed,
|
||||||
} else {
|
// so we can just make the hidden type be `!`.
|
||||||
// We failed to resolve the opaque type or it
|
// For backwards compatibility reasons, we fall back to
|
||||||
// resolves to itself. We interpret this as the
|
// `()` until we the diverging default is changed.
|
||||||
// no values of the hidden type ever being constructed,
|
Ty::new_diverging_default(tcx)
|
||||||
// so we can just make the hidden type be `!`.
|
|
||||||
// For backwards compatibility reasons, we fall back to
|
|
||||||
// `()` until we the diverging default is changed.
|
|
||||||
Ty::new_diverging_default(tcx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -827,20 +827,18 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||||||
|
|
||||||
if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args
|
if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args
|
||||||
== num_trait_generics_except_self
|
== num_trait_generics_except_self
|
||||||
|
&& let Some(span) = self.gen_args.span_ext()
|
||||||
|
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||||
{
|
{
|
||||||
if let Some(span) = self.gen_args.span_ext()
|
let sugg = vec![
|
||||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
(
|
||||||
{
|
self.path_segment.ident.span,
|
||||||
let sugg = vec![
|
format!("{}::{}", snippet, self.path_segment.ident),
|
||||||
(
|
),
|
||||||
self.path_segment.ident.span,
|
(span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
|
||||||
format!("{}::{}", snippet, self.path_segment.ident),
|
];
|
||||||
),
|
|
||||||
(span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
|
|
||||||
];
|
|
||||||
|
|
||||||
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
|
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,13 +562,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
tcx.const_param_default(param.def_id)
|
tcx.const_param_default(param.def_id)
|
||||||
.instantiate(tcx, preceding_args)
|
.instantiate(tcx, preceding_args)
|
||||||
.into()
|
.into()
|
||||||
|
} else if infer_args {
|
||||||
|
self.lowerer.ct_infer(Some(param), self.span).into()
|
||||||
} else {
|
} else {
|
||||||
if infer_args {
|
// We've already errored above about the mismatch.
|
||||||
self.lowerer.ct_infer(Some(param), self.span).into()
|
ty::Const::new_misc_error(tcx).into()
|
||||||
} else {
|
|
||||||
// We've already errored above about the mismatch.
|
|
||||||
ty::Const::new_misc_error(tcx).into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -732,12 +732,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
}
|
}
|
||||||
_ => return Err(CastError::NonScalar),
|
_ => return Err(CastError::NonScalar),
|
||||||
};
|
};
|
||||||
if let ty::Adt(adt_def, _) = *self.expr_ty.kind() {
|
if let ty::Adt(adt_def, _) = *self.expr_ty.kind()
|
||||||
if adt_def.did().krate != LOCAL_CRATE {
|
&& adt_def.did().krate != LOCAL_CRATE
|
||||||
if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) {
|
&& adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive)
|
||||||
return Err(CastError::ForeignNonExhaustiveAdt);
|
{
|
||||||
}
|
return Err(CastError::ForeignNonExhaustiveAdt);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match (t_from, t_cast) {
|
match (t_from, t_cast) {
|
||||||
// These types have invariants! can't cast into them.
|
// These types have invariants! can't cast into them.
|
||||||
|
@ -1780,16 +1780,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the programmer specified correct number of fields.
|
// Make sure the programmer specified correct number of fields.
|
||||||
if adt_kind == AdtKind::Union {
|
if adt_kind == AdtKind::Union && hir_fields.len() != 1 {
|
||||||
if hir_fields.len() != 1 {
|
struct_span_code_err!(
|
||||||
struct_span_code_err!(
|
self.dcx(),
|
||||||
self.dcx(),
|
span,
|
||||||
span,
|
E0784,
|
||||||
E0784,
|
"union expressions should have exactly one field",
|
||||||
"union expressions should have exactly one field",
|
)
|
||||||
)
|
.emit();
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If check_expr_struct_fields hit an error, do not attempt to populate
|
// If check_expr_struct_fields hit an error, do not attempt to populate
|
||||||
@ -2904,21 +2902,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
|
candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else {
|
} else if let Some(field_name) =
|
||||||
if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) {
|
find_best_match_for_name(&field_names, field.name, None)
|
||||||
err.span_suggestion_verbose(
|
{
|
||||||
field.span,
|
err.span_suggestion_verbose(
|
||||||
"a field with a similar name exists",
|
field.span,
|
||||||
format!("{unwrap}{}", field_name),
|
"a field with a similar name exists",
|
||||||
Applicability::MaybeIncorrect,
|
format!("{unwrap}{}", field_name),
|
||||||
);
|
Applicability::MaybeIncorrect,
|
||||||
} else if !field_names.is_empty() {
|
);
|
||||||
let is = if field_names.len() == 1 { " is" } else { "s are" };
|
} else if !field_names.is_empty() {
|
||||||
err.note(format!(
|
let is = if field_names.len() == 1 { " is" } else { "s are" };
|
||||||
"available field{is}: {}",
|
err.note(
|
||||||
self.name_series_display(field_names),
|
format!("available field{is}: {}", self.name_series_display(field_names),),
|
||||||
));
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err
|
err
|
||||||
|
@ -2565,7 +2565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
other_generic_param.name.ident() == generic_param.name.ident()
|
other_generic_param.name.ident() == generic_param.name.ident()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
idxs_matched.push(other_idx.into());
|
idxs_matched.push(other_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if idxs_matched.is_empty() {
|
if idxs_matched.is_empty() {
|
||||||
|
@ -158,14 +158,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else if !self.fcx.tcx.features().unsized_locals {
|
||||||
if !self.fcx.tcx.features().unsized_locals {
|
self.fcx.require_type_is_sized(
|
||||||
self.fcx.require_type_is_sized(
|
var_ty,
|
||||||
var_ty,
|
p.span,
|
||||||
p.span,
|
ObligationCauseCode::VariableType(p.hir_id),
|
||||||
ObligationCauseCode::VariableType(p.hir_id),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -1252,11 +1252,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& suggested_bounds.contains(parent)
|
&& suggested_bounds.contains(parent)
|
||||||
{
|
{
|
||||||
// We don't suggest `PartialEq` when we already suggest `Eq`.
|
// We don't suggest `PartialEq` when we already suggest `Eq`.
|
||||||
} else if !suggested_bounds.contains(pred) {
|
} else if !suggested_bounds.contains(pred)
|
||||||
if collect_type_param_suggestions(self_ty, *pred, &p) {
|
&& collect_type_param_suggestions(self_ty, *pred, &p)
|
||||||
suggested = true;
|
{
|
||||||
suggested_bounds.insert(pred);
|
suggested = true;
|
||||||
}
|
suggested_bounds.insert(pred);
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
match parent_pred {
|
match parent_pred {
|
||||||
@ -1267,14 +1267,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
if !suggested
|
if !suggested
|
||||||
&& !suggested_bounds.contains(pred)
|
&& !suggested_bounds.contains(pred)
|
||||||
&& !suggested_bounds.contains(parent_pred)
|
&& !suggested_bounds.contains(parent_pred)
|
||||||
{
|
&& collect_type_param_suggestions(
|
||||||
if collect_type_param_suggestions(
|
|
||||||
self_ty,
|
self_ty,
|
||||||
*parent_pred,
|
*parent_pred,
|
||||||
&p,
|
&p,
|
||||||
) {
|
)
|
||||||
suggested_bounds.insert(pred);
|
{
|
||||||
}
|
suggested_bounds.insert(pred);
|
||||||
}
|
}
|
||||||
format!("`{p}`\nwhich is required by `{parent_p}`")
|
format!("`{p}`\nwhich is required by `{parent_p}`")
|
||||||
}
|
}
|
||||||
|
@ -417,12 +417,10 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
|
|||||||
fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
|
fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
|
||||||
if let Some(value) = item.value_str() {
|
if let Some(value) = item.value_str() {
|
||||||
value
|
value
|
||||||
|
} else if let Some(ident) = item.ident() {
|
||||||
|
tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
|
||||||
} else {
|
} else {
|
||||||
if let Some(ident) = item.ident() {
|
tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() });
|
||||||
tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
|
|
||||||
} else {
|
|
||||||
tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,10 +429,8 @@ impl MissingDoc {
|
|||||||
// Only check publicly-visible items, using the result from the privacy pass.
|
// Only check publicly-visible items, using the result from the privacy pass.
|
||||||
// It's an option so the crate root can also use this function (it doesn't
|
// It's an option so the crate root can also use this function (it doesn't
|
||||||
// have a `NodeId`).
|
// have a `NodeId`).
|
||||||
if def_id != CRATE_DEF_ID {
|
if def_id != CRATE_DEF_ID && !cx.effective_visibilities.is_exported(def_id) {
|
||||||
if !cx.effective_visibilities.is_exported(def_id) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
|
let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
|
||||||
|
@ -444,10 +444,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
// the `-Z force-unstable-if-unmarked` flag present (we're
|
// the `-Z force-unstable-if-unmarked` flag present (we're
|
||||||
// compiling a compiler crate), then let this missing feature
|
// compiling a compiler crate), then let this missing feature
|
||||||
// annotation slide.
|
// annotation slide.
|
||||||
if feature == sym::rustc_private && issue == NonZero::new(27812) {
|
if feature == sym::rustc_private
|
||||||
if self.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
&& issue == NonZero::new(27812)
|
||||||
return EvalResult::Allow;
|
&& self.sess.opts.unstable_opts.force_unstable_if_unmarked
|
||||||
}
|
{
|
||||||
|
return EvalResult::Allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(allow_unstable, AllowUnstable::Yes) {
|
if matches!(allow_unstable, AllowUnstable::Yes) {
|
||||||
|
@ -448,22 +448,20 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
|||||||
bad: uninit_range,
|
bad: uninit_range,
|
||||||
}))
|
}))
|
||||||
})?;
|
})?;
|
||||||
if !Prov::OFFSET_IS_ADDR {
|
if !Prov::OFFSET_IS_ADDR && !self.provenance.range_empty(range, cx) {
|
||||||
if !self.provenance.range_empty(range, cx) {
|
// Find the provenance.
|
||||||
// Find the provenance.
|
let (offset, _prov) = self
|
||||||
let (offset, _prov) = self
|
.provenance
|
||||||
.provenance
|
.range_get_ptrs(range, cx)
|
||||||
.range_get_ptrs(range, cx)
|
.first()
|
||||||
.first()
|
.copied()
|
||||||
.copied()
|
.expect("there must be provenance somewhere here");
|
||||||
.expect("there must be provenance somewhere here");
|
let start = offset.max(range.start); // the pointer might begin before `range`!
|
||||||
let start = offset.max(range.start); // the pointer might begin before `range`!
|
let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
|
||||||
let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
|
return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
|
||||||
return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
|
access: range,
|
||||||
access: range,
|
bad: AllocRange::from(start..end),
|
||||||
bad: AllocRange::from(start..end),
|
})));
|
||||||
})));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(self.get_bytes_unchecked(range))
|
Ok(self.get_bytes_unchecked(range))
|
||||||
}
|
}
|
||||||
|
@ -208,12 +208,10 @@ fn dump_path<'tcx>(
|
|||||||
|
|
||||||
let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
|
let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number {
|
||||||
String::new()
|
String::new()
|
||||||
|
} else if pass_num {
|
||||||
|
format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
|
||||||
} else {
|
} else {
|
||||||
if pass_num {
|
".-------".to_string()
|
||||||
format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count)
|
|
||||||
} else {
|
|
||||||
".-------".to_string()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let crate_name = tcx.crate_name(source.def_id().krate);
|
let crate_name = tcx.crate_name(source.def_id().krate);
|
||||||
|
@ -396,7 +396,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
|
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
|
||||||
}
|
}
|
||||||
Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
|
Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
|
||||||
Err(err) => Err(Either::Right(err.into())),
|
Err(err) => Err(Either::Right(err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConstKind::Value(ty, val) => Ok((ty, val)),
|
ConstKind::Value(ty, val) => Ok((ty, val)),
|
||||||
|
@ -2606,33 +2606,31 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
/// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
|
/// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
|
||||||
/// and print out the args if not.
|
/// and print out the args if not.
|
||||||
pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
|
pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) && !self.check_args_compatible(def_id, args) {
|
||||||
if !self.check_args_compatible(def_id, args) {
|
if let DefKind::AssocTy = self.def_kind(def_id)
|
||||||
if let DefKind::AssocTy = self.def_kind(def_id)
|
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
|
||||||
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
|
{
|
||||||
{
|
bug!(
|
||||||
bug!(
|
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
|
||||||
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
|
self.def_path_str(def_id),
|
||||||
self.def_path_str(def_id),
|
args,
|
||||||
args,
|
// Make `[Self, GAT_ARGS...]` (this could be simplified)
|
||||||
// Make `[Self, GAT_ARGS...]` (this could be simplified)
|
self.mk_args_from_iter(
|
||||||
self.mk_args_from_iter(
|
[self.types.self_param.into()].into_iter().chain(
|
||||||
[self.types.self_param.into()].into_iter().chain(
|
self.generics_of(def_id)
|
||||||
self.generics_of(def_id)
|
.own_args(ty::GenericArgs::identity_for_item(self, def_id))
|
||||||
.own_args(ty::GenericArgs::identity_for_item(self, def_id))
|
.iter()
|
||||||
.iter()
|
.copied()
|
||||||
.copied()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
} else {
|
);
|
||||||
bug!(
|
} else {
|
||||||
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
|
bug!(
|
||||||
self.def_path_str(def_id),
|
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
|
||||||
args,
|
self.def_path_str(def_id),
|
||||||
ty::GenericArgs::identity_for_item(self, def_id)
|
args,
|
||||||
);
|
ty::GenericArgs::identity_for_item(self, def_id)
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1183,10 +1183,10 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
|
|||||||
//
|
//
|
||||||
// This is not part of `codegen_fn_attrs` as it can differ between crates
|
// This is not part of `codegen_fn_attrs` as it can differ between crates
|
||||||
// and therefore cannot be computed in core.
|
// and therefore cannot be computed in core.
|
||||||
if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort {
|
if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort
|
||||||
if tcx.is_lang_item(did, LangItem::DropInPlace) {
|
&& tcx.is_lang_item(did, LangItem::DropInPlace)
|
||||||
return false;
|
{
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,7 +1526,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
|
|
||||||
let precedence = |binop: rustc_middle::mir::BinOp| {
|
let precedence = |binop: rustc_middle::mir::BinOp| {
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
|
AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
|
||||||
};
|
};
|
||||||
let op_precedence = precedence(op);
|
let op_precedence = precedence(op);
|
||||||
let formatted_op = op.to_hir_binop().as_str();
|
let formatted_op = op.to_hir_binop().as_str();
|
||||||
@ -3361,10 +3361,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
|
|||||||
// name.
|
// name.
|
||||||
//
|
//
|
||||||
// Any stable ordering would be fine here though.
|
// Any stable ordering would be fine here though.
|
||||||
if *v.get() != symbol {
|
if *v.get() != symbol && v.get().as_str() > symbol.as_str() {
|
||||||
if v.get().as_str() > symbol.as_str() {
|
v.insert(symbol);
|
||||||
v.insert(symbol);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vacant(v) => {
|
Vacant(v) => {
|
||||||
|
@ -268,10 +268,9 @@ impl Builder<'_, '_> {
|
|||||||
pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) {
|
pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) {
|
||||||
if let Some(coverage_info) = self.coverage_info.as_mut()
|
if let Some(coverage_info) = self.coverage_info.as_mut()
|
||||||
&& let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
|
&& let Some(mcdc_info) = coverage_info.mcdc_info.as_mut()
|
||||||
|
&& mcdc_info.state.decision_ctx_stack.pop().is_none()
|
||||||
{
|
{
|
||||||
if mcdc_info.state.decision_ctx_stack.pop().is_none() {
|
bug!("Unexpected empty decision stack");
|
||||||
bug!("Unexpected empty decision stack");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,19 +95,19 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
|
|||||||
// Check for assignment to fields of a constant
|
// Check for assignment to fields of a constant
|
||||||
// Assigning directly to a constant (e.g. `FOO = true;`) is a hard error,
|
// Assigning directly to a constant (e.g. `FOO = true;`) is a hard error,
|
||||||
// so emitting a lint would be redundant.
|
// so emitting a lint would be redundant.
|
||||||
if !lhs.projection.is_empty() {
|
if !lhs.projection.is_empty()
|
||||||
if let Some(def_id) = self.is_const_item_without_destructor(lhs.local)
|
&& let Some(def_id) = self.is_const_item_without_destructor(lhs.local)
|
||||||
&& let Some((lint_root, span, item)) =
|
&& let Some((lint_root, span, item)) =
|
||||||
self.should_lint_const_item_usage(lhs, def_id, loc)
|
self.should_lint_const_item_usage(lhs, def_id, loc)
|
||||||
{
|
{
|
||||||
self.tcx.emit_node_span_lint(
|
self.tcx.emit_node_span_lint(
|
||||||
CONST_ITEM_MUTATION,
|
CONST_ITEM_MUTATION,
|
||||||
lint_root,
|
lint_root,
|
||||||
span,
|
span,
|
||||||
errors::ConstMutate::Modify { konst: item },
|
errors::ConstMutate::Modify { konst: item },
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are looking for MIR of the form:
|
// We are looking for MIR of the form:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
|
@ -168,17 +168,16 @@ pub(super) fn deduced_param_attrs<'tcx>(
|
|||||||
// Codegen won't use this information for anything if all the function parameters are passed
|
// Codegen won't use this information for anything if all the function parameters are passed
|
||||||
// directly. Detect that and bail, for compilation speed.
|
// directly. Detect that and bail, for compilation speed.
|
||||||
let fn_ty = tcx.type_of(def_id).instantiate_identity();
|
let fn_ty = tcx.type_of(def_id).instantiate_identity();
|
||||||
if matches!(fn_ty.kind(), ty::FnDef(..)) {
|
if matches!(fn_ty.kind(), ty::FnDef(..))
|
||||||
if fn_ty
|
&& fn_ty
|
||||||
.fn_sig(tcx)
|
.fn_sig(tcx)
|
||||||
.inputs()
|
.inputs()
|
||||||
.skip_binder()
|
.skip_binder()
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.all(type_will_always_be_passed_directly)
|
.all(type_will_always_be_passed_directly)
|
||||||
{
|
{
|
||||||
return &[];
|
return &[];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't deduce any attributes for functions that have no MIR.
|
// Don't deduce any attributes for functions that have no MIR.
|
||||||
|
@ -378,19 +378,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||||||
if let (Some(l), Some(r)) = (l, r)
|
if let (Some(l), Some(r)) = (l, r)
|
||||||
&& l.layout.ty.is_integral()
|
&& l.layout.ty.is_integral()
|
||||||
&& op.is_overflowing()
|
&& op.is_overflowing()
|
||||||
{
|
&& self.use_ecx(|this| {
|
||||||
if self.use_ecx(|this| {
|
|
||||||
let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair();
|
let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair();
|
||||||
overflow.to_bool()
|
overflow.to_bool()
|
||||||
})? {
|
})?
|
||||||
self.report_assert_as_lint(
|
{
|
||||||
location,
|
self.report_assert_as_lint(
|
||||||
AssertLintKind::ArithmeticOverflow,
|
location,
|
||||||
AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
|
AssertLintKind::ArithmeticOverflow,
|
||||||
);
|
AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
|
||||||
return None;
|
);
|
||||||
}
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,10 +504,8 @@ fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'t
|
|||||||
|
|
||||||
let mut overlap = 0;
|
let mut overlap = 0;
|
||||||
for (item, data) in src_cgu.items().iter() {
|
for (item, data) in src_cgu.items().iter() {
|
||||||
if data.inlined {
|
if data.inlined && dst_cgu.items().contains_key(item) {
|
||||||
if dst_cgu.items().contains_key(item) {
|
overlap += data.size_estimate;
|
||||||
overlap += data.size_estimate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
overlap
|
overlap
|
||||||
|
@ -185,10 +185,8 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||||||
for var in var_infos.iter_mut() {
|
for var in var_infos.iter_mut() {
|
||||||
// We simply put all regions from the input into the highest
|
// We simply put all regions from the input into the highest
|
||||||
// compressed universe, so we only deal with them at the end.
|
// compressed universe, so we only deal with them at the end.
|
||||||
if !var.is_region() {
|
if !var.is_region() && is_existential == var.is_existential() {
|
||||||
if is_existential == var.is_existential() {
|
update_uv(var, orig_uv, is_existential)
|
||||||
update_uv(var, orig_uv, is_existential)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -883,7 +883,6 @@ where
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
|
.chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
|
||||||
elaborate::supertrait_def_ids(self.cx(), principal_def_id)
|
elaborate::supertrait_def_ids(self.cx(), principal_def_id)
|
||||||
.into_iter()
|
|
||||||
.filter(|def_id| self.cx().trait_is_auto(*def_id))
|
.filter(|def_id| self.cx().trait_is_auto(*def_id))
|
||||||
}))
|
}))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -383,7 +383,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.capture_state
|
self.capture_state
|
||||||
.parser_replacements
|
.parser_replacements
|
||||||
.drain(parser_replacements_start..parser_replacements_end)
|
.drain(parser_replacements_start..parser_replacements_end)
|
||||||
.chain(inner_attr_parser_replacements.into_iter())
|
.chain(inner_attr_parser_replacements)
|
||||||
.map(|(parser_range, data)| {
|
.map(|(parser_range, data)| {
|
||||||
(NodeRange::new(parser_range, collect_pos.start_pos), data)
|
(NodeRange::new(parser_range, collect_pos.start_pos), data)
|
||||||
})
|
})
|
||||||
|
@ -2554,13 +2554,12 @@ impl<'a> Parser<'a> {
|
|||||||
let maybe_fatarrow = self.token.clone();
|
let maybe_fatarrow = self.token.clone();
|
||||||
let block = if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
let block = if self.check(&token::OpenDelim(Delimiter::Brace)) {
|
||||||
self.parse_block()?
|
self.parse_block()?
|
||||||
|
} else if let Some(block) = recover_block_from_condition(self) {
|
||||||
|
block
|
||||||
} else {
|
} else {
|
||||||
if let Some(block) = recover_block_from_condition(self) {
|
self.error_on_extra_if(&cond)?;
|
||||||
block
|
// Parse block, which will always fail, but we can add a nice note to the error
|
||||||
} else {
|
self.parse_block().map_err(|mut err| {
|
||||||
self.error_on_extra_if(&cond)?;
|
|
||||||
// Parse block, which will always fail, but we can add a nice note to the error
|
|
||||||
self.parse_block().map_err(|mut err| {
|
|
||||||
if self.prev_token == token::Semi
|
if self.prev_token == token::Semi
|
||||||
&& self.token == token::AndAnd
|
&& self.token == token::AndAnd
|
||||||
&& let maybe_let = self.look_ahead(1, |t| t.clone())
|
&& let maybe_let = self.look_ahead(1, |t| t.clone())
|
||||||
@ -2592,7 +2591,6 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
err
|
err
|
||||||
})?
|
})?
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.error_on_if_block_attrs(lo, false, block.span, attrs);
|
self.error_on_if_block_attrs(lo, false, block.span, attrs);
|
||||||
block
|
block
|
||||||
|
@ -1588,7 +1588,7 @@ impl<'a> Parser<'a> {
|
|||||||
(thin_vec![], Recovered::Yes(guar))
|
(thin_vec![], Recovered::Yes(guar))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
VariantData::Struct { fields, recovered: recovered.into() }
|
VariantData::Struct { fields, recovered }
|
||||||
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||||
let body = match this.parse_tuple_struct_body() {
|
let body = match this.parse_tuple_struct_body() {
|
||||||
Ok(body) => body,
|
Ok(body) => body,
|
||||||
@ -1672,7 +1672,7 @@ impl<'a> Parser<'a> {
|
|||||||
class_name.span,
|
class_name.span,
|
||||||
generics.where_clause.has_where_token,
|
generics.where_clause.has_where_token,
|
||||||
)?;
|
)?;
|
||||||
VariantData::Struct { fields, recovered: recovered.into() }
|
VariantData::Struct { fields, recovered }
|
||||||
}
|
}
|
||||||
// No `where` so: `struct Foo<T>;`
|
// No `where` so: `struct Foo<T>;`
|
||||||
} else if self.eat(&token::Semi) {
|
} else if self.eat(&token::Semi) {
|
||||||
@ -1684,7 +1684,7 @@ impl<'a> Parser<'a> {
|
|||||||
class_name.span,
|
class_name.span,
|
||||||
generics.where_clause.has_where_token,
|
generics.where_clause.has_where_token,
|
||||||
)?;
|
)?;
|
||||||
VariantData::Struct { fields, recovered: recovered.into() }
|
VariantData::Struct { fields, recovered }
|
||||||
// Tuple-style struct definition with optional where-clause.
|
// Tuple-style struct definition with optional where-clause.
|
||||||
} else if self.token == token::OpenDelim(Delimiter::Parenthesis) {
|
} else if self.token == token::OpenDelim(Delimiter::Parenthesis) {
|
||||||
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
|
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
|
||||||
@ -1713,14 +1713,14 @@ impl<'a> Parser<'a> {
|
|||||||
class_name.span,
|
class_name.span,
|
||||||
generics.where_clause.has_where_token,
|
generics.where_clause.has_where_token,
|
||||||
)?;
|
)?;
|
||||||
VariantData::Struct { fields, recovered: recovered.into() }
|
VariantData::Struct { fields, recovered }
|
||||||
} else if self.token == token::OpenDelim(Delimiter::Brace) {
|
} else if self.token == token::OpenDelim(Delimiter::Brace) {
|
||||||
let (fields, recovered) = self.parse_record_struct_body(
|
let (fields, recovered) = self.parse_record_struct_body(
|
||||||
"union",
|
"union",
|
||||||
class_name.span,
|
class_name.span,
|
||||||
generics.where_clause.has_where_token,
|
generics.where_clause.has_where_token,
|
||||||
)?;
|
)?;
|
||||||
VariantData::Struct { fields, recovered: recovered.into() }
|
VariantData::Struct { fields, recovered }
|
||||||
} else {
|
} else {
|
||||||
let token_str = super::token_descr(&self.token);
|
let token_str = super::token_descr(&self.token);
|
||||||
let msg = format!("expected `where` or `{{` after union name, found {token_str}");
|
let msg = format!("expected `where` or `{{` after union name, found {token_str}");
|
||||||
|
@ -1359,13 +1359,11 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> {
|
fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> {
|
||||||
Ok(if let Some(args) = self.parse_delim_args_inner() {
|
Ok(if let Some(args) = self.parse_delim_args_inner() {
|
||||||
AttrArgs::Delimited(args)
|
AttrArgs::Delimited(args)
|
||||||
|
} else if self.eat(&token::Eq) {
|
||||||
|
let eq_span = self.prev_token.span;
|
||||||
|
AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
|
||||||
} else {
|
} else {
|
||||||
if self.eat(&token::Eq) {
|
AttrArgs::Empty
|
||||||
let eq_span = self.prev_token.span;
|
|
||||||
AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
|
|
||||||
} else {
|
|
||||||
AttrArgs::Empty
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1336,21 +1336,19 @@ impl<'a> Parser<'a> {
|
|||||||
vec![(first_etc_span, String::new())],
|
vec![(first_etc_span, String::new())],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
} else {
|
} else if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span {
|
||||||
if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span {
|
// We have `.., x`.
|
||||||
// We have `.., x`.
|
err.multipart_suggestion(
|
||||||
err.multipart_suggestion(
|
"move the `..` to the end of the field list",
|
||||||
"move the `..` to the end of the field list",
|
vec![
|
||||||
vec![
|
(first_etc_span, String::new()),
|
||||||
(first_etc_span, String::new()),
|
(
|
||||||
(
|
self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()),
|
||||||
self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()),
|
format!("{} .. }}", if ate_comma { "" } else { "," }),
|
||||||
format!("{} .. }}", if ate_comma { "" } else { "," }),
|
),
|
||||||
),
|
],
|
||||||
],
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -671,12 +671,12 @@ impl<'a> Parser<'a> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !self.token.kind.should_end_const_arg() {
|
if !self.token.kind.should_end_const_arg()
|
||||||
if self.handle_ambiguous_unbraced_const_arg(&mut args)? {
|
&& self.handle_ambiguous_unbraced_const_arg(&mut args)?
|
||||||
// We've managed to (partially) recover, so continue trying to parse
|
{
|
||||||
// arguments.
|
// We've managed to (partially) recover, so continue trying to parse
|
||||||
continue;
|
// arguments.
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -192,13 +192,11 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
|
||||||
if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
|
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
|
||||||
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
|
span: unsafe_span,
|
||||||
span: unsafe_span,
|
name: attr_item.path.clone(),
|
||||||
name: attr_item.path.clone(),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2169,17 +2169,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
attr.span,
|
attr.span,
|
||||||
errors::MacroExport::TooManyItems,
|
errors::MacroExport::TooManyItems,
|
||||||
);
|
);
|
||||||
} else {
|
} else if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
|
||||||
if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
|
self.tcx.emit_node_span_lint(
|
||||||
self.tcx.emit_node_span_lint(
|
INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||||
INVALID_MACRO_EXPORT_ARGUMENTS,
|
hir_id,
|
||||||
hir_id,
|
meta_item_list[0].span(),
|
||||||
meta_item_list[0].span(),
|
errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
|
||||||
errors::MacroExport::UnknownItem {
|
);
|
||||||
name: meta_item_list[0].name_or_empty(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// special case when `#[macro_export]` is applied to a macro 2.0
|
// special case when `#[macro_export]` is applied to a macro 2.0
|
||||||
|
@ -1500,15 +1500,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(name) = self.should_warn(var) {
|
||||||
if let Some(name) = self.should_warn(var) {
|
self.ir.tcx.emit_node_span_lint(
|
||||||
self.ir.tcx.emit_node_span_lint(
|
lint::builtin::UNUSED_VARIABLES,
|
||||||
lint::builtin::UNUSED_VARIABLES,
|
var_hir_id,
|
||||||
var_hir_id,
|
vec![span],
|
||||||
vec![span],
|
errors::UnusedVarMaybeCaptureRef { name },
|
||||||
errors::UnusedVarMaybeCaptureRef { name },
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,16 +174,14 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
|
|
||||||
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
|
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
|
||||||
// check if the function/method is const or the parent impl block is const
|
// check if the function/method is const or the parent impl block is const
|
||||||
if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) {
|
if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig)
|
||||||
if fn_sig.header.abi != Abi::RustIntrinsic && !fn_sig.header.is_const() {
|
&& fn_sig.header.abi != Abi::RustIntrinsic
|
||||||
if !self.in_trait_impl
|
&& !fn_sig.header.is_const()
|
||||||
|| (self.in_trait_impl && !self.tcx.is_const_fn_raw(def_id.to_def_id()))
|
&& (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
|
||||||
{
|
{
|
||||||
self.tcx
|
self.tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
|
.emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `impl const Trait for Type` items forward their const stability to their
|
// `impl const Trait for Type` items forward their const stability to their
|
||||||
|
@ -1233,64 +1233,63 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
&& ns == namespace
|
&& ns == namespace
|
||||||
&& in_module != parent_scope.module
|
&& in_module != parent_scope.module
|
||||||
&& !ident.span.normalize_to_macros_2_0().from_expansion()
|
&& !ident.span.normalize_to_macros_2_0().from_expansion()
|
||||||
|
&& filter_fn(res)
|
||||||
{
|
{
|
||||||
if filter_fn(res) {
|
// create the path
|
||||||
// create the path
|
let mut segms = if lookup_ident.span.at_least_rust_2018() {
|
||||||
let mut segms = if lookup_ident.span.at_least_rust_2018() {
|
// crate-local absolute paths start with `crate::` in edition 2018
|
||||||
// crate-local absolute paths start with `crate::` in edition 2018
|
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
|
||||||
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
|
crate_path.clone()
|
||||||
crate_path.clone()
|
} else {
|
||||||
|
ThinVec::new()
|
||||||
|
};
|
||||||
|
segms.append(&mut path_segments.clone());
|
||||||
|
|
||||||
|
segms.push(ast::PathSegment::from_ident(ident));
|
||||||
|
let path = Path { span: name_binding.span, segments: segms, tokens: None };
|
||||||
|
|
||||||
|
if child_accessible {
|
||||||
|
// Remove invisible match if exists
|
||||||
|
if let Some(idx) = candidates
|
||||||
|
.iter()
|
||||||
|
.position(|v: &ImportSuggestion| v.did == did && !v.accessible)
|
||||||
|
{
|
||||||
|
candidates.remove(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
||||||
|
// See if we're recommending TryFrom, TryInto, or FromIterator and add
|
||||||
|
// a note about editions
|
||||||
|
let note = if let Some(did) = did {
|
||||||
|
let requires_note = !did.is_local()
|
||||||
|
&& this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
|
||||||
|
|attr| {
|
||||||
|
[sym::TryInto, sym::TryFrom, sym::FromIterator]
|
||||||
|
.map(|x| Some(x))
|
||||||
|
.contains(&attr.value_str())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
requires_note.then(|| {
|
||||||
|
format!(
|
||||||
|
"'{}' is included in the prelude starting in Edition 2021",
|
||||||
|
path_names_to_string(&path)
|
||||||
|
)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
ThinVec::new()
|
None
|
||||||
};
|
};
|
||||||
segms.append(&mut path_segments.clone());
|
|
||||||
|
|
||||||
segms.push(ast::PathSegment::from_ident(ident));
|
candidates.push(ImportSuggestion {
|
||||||
let path = Path { span: name_binding.span, segments: segms, tokens: None };
|
did,
|
||||||
|
descr: res.descr(),
|
||||||
if child_accessible {
|
path,
|
||||||
// Remove invisible match if exists
|
accessible: child_accessible,
|
||||||
if let Some(idx) = candidates
|
doc_visible: child_doc_visible,
|
||||||
.iter()
|
note,
|
||||||
.position(|v: &ImportSuggestion| v.did == did && !v.accessible)
|
via_import,
|
||||||
{
|
});
|
||||||
candidates.remove(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
|
||||||
// See if we're recommending TryFrom, TryInto, or FromIterator and add
|
|
||||||
// a note about editions
|
|
||||||
let note = if let Some(did) = did {
|
|
||||||
let requires_note = !did.is_local()
|
|
||||||
&& this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
|
|
||||||
|attr| {
|
|
||||||
[sym::TryInto, sym::TryFrom, sym::FromIterator]
|
|
||||||
.map(|x| Some(x))
|
|
||||||
.contains(&attr.value_str())
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
requires_note.then(|| {
|
|
||||||
format!(
|
|
||||||
"'{}' is included in the prelude starting in Edition 2021",
|
|
||||||
path_names_to_string(&path)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
candidates.push(ImportSuggestion {
|
|
||||||
did,
|
|
||||||
descr: res.descr(),
|
|
||||||
path,
|
|
||||||
accessible: child_accessible,
|
|
||||||
doc_visible: child_doc_visible,
|
|
||||||
note,
|
|
||||||
via_import,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -958,12 +958,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
|
if !restricted_shadowing
|
||||||
if let NameBindingKind::Import { import, .. } = binding.kind
|
&& binding.expansion != LocalExpnId::ROOT
|
||||||
&& matches!(import.kind, ImportKind::MacroExport)
|
&& let NameBindingKind::Import { import, .. } = binding.kind
|
||||||
{
|
&& matches!(import.kind, ImportKind::MacroExport)
|
||||||
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
{
|
||||||
}
|
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.record_use(ident, binding, used);
|
self.record_use(ident, binding, used);
|
||||||
|
@ -1256,28 +1256,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)),
|
extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else if ns == TypeNS {
|
||||||
if ns == TypeNS {
|
let err = if crate_private_reexport {
|
||||||
let err = if crate_private_reexport {
|
self.dcx()
|
||||||
self.dcx().create_err(CannotBeReexportedCratePublicNS {
|
.create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
|
||||||
span: import.span,
|
|
||||||
ident,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
self.dcx()
|
|
||||||
.create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
|
|
||||||
};
|
|
||||||
err.emit();
|
|
||||||
} else {
|
} else {
|
||||||
let mut err = if crate_private_reexport {
|
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
|
||||||
self.dcx()
|
};
|
||||||
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
|
err.emit();
|
||||||
} else {
|
} else {
|
||||||
self.dcx()
|
let mut err = if crate_private_reexport {
|
||||||
.create_err(CannotBeReexportedPrivate { span: import.span, ident })
|
self.dcx()
|
||||||
};
|
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
|
||||||
|
} else {
|
||||||
|
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
|
||||||
|
};
|
||||||
|
|
||||||
match binding.kind {
|
match binding.kind {
|
||||||
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
|
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
|
||||||
// exclude decl_macro
|
// exclude decl_macro
|
||||||
if self.get_macro_by_def_id(def_id).macro_rules =>
|
if self.get_macro_by_def_id(def_id).macro_rules =>
|
||||||
@ -1293,8 +1288,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4781,16 +4781,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||||||
if let Some(res) = res
|
if let Some(res) = res
|
||||||
&& let Some(def_id) = res.opt_def_id()
|
&& let Some(def_id) = res.opt_def_id()
|
||||||
&& !def_id.is_local()
|
&& !def_id.is_local()
|
||||||
|
&& self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
|
||||||
|
&& matches!(
|
||||||
|
self.r.tcx.sess.opts.resolve_doc_links,
|
||||||
|
ResolveDocLinks::ExportedMetadata
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
|
// Encoding foreign def ids in proc macro crate metadata will ICE.
|
||||||
&& matches!(
|
return None;
|
||||||
self.r.tcx.sess.opts.resolve_doc_links,
|
|
||||||
ResolveDocLinks::ExportedMetadata
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Encoding foreign def ids in proc macro crate metadata will ICE.
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
});
|
});
|
||||||
|
@ -2255,25 +2255,24 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool {
|
fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool {
|
||||||
if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment
|
if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment
|
||||||
&& let ast::ExprKind::Path(None, ref path) = lhs.kind
|
&& let ast::ExprKind::Path(None, ref path) = lhs.kind
|
||||||
|
&& !ident_span.from_expansion()
|
||||||
{
|
{
|
||||||
if !ident_span.from_expansion() {
|
let (span, text) = match path.segments.first() {
|
||||||
let (span, text) = match path.segments.first() {
|
Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
|
||||||
Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
|
// a special case for #117894
|
||||||
// a special case for #117894
|
let name = name.strip_prefix('_').unwrap_or(name);
|
||||||
let name = name.strip_prefix('_').unwrap_or(name);
|
(ident_span, format!("let {name}"))
|
||||||
(ident_span, format!("let {name}"))
|
}
|
||||||
}
|
_ => (ident_span.shrink_to_lo(), "let ".to_string()),
|
||||||
_ => (ident_span.shrink_to_lo(), "let ".to_string()),
|
};
|
||||||
};
|
|
||||||
|
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"you might have meant to introduce a new binding",
|
"you might have meant to introduce a new binding",
|
||||||
text,
|
text,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -270,12 +270,10 @@ fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, Malfor
|
|||||||
// Give a helpful error message instead of completely ignoring the angle brackets.
|
// Give a helpful error message instead of completely ignoring the angle brackets.
|
||||||
return Err(MalformedGenerics::HasFullyQualifiedSyntax);
|
return Err(MalformedGenerics::HasFullyQualifiedSyntax);
|
||||||
}
|
}
|
||||||
|
} else if param_depth == 0 {
|
||||||
|
stripped_segment.push(c);
|
||||||
} else {
|
} else {
|
||||||
if param_depth == 0 {
|
latest_generics_chunk.push(c);
|
||||||
stripped_segment.push(c);
|
|
||||||
} else {
|
|
||||||
latest_generics_chunk.push(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +207,12 @@ fn encode_fnsig<'tcx>(
|
|||||||
if fn_sig.c_variadic {
|
if fn_sig.c_variadic {
|
||||||
s.push('z');
|
s.push('z');
|
||||||
}
|
}
|
||||||
|
} else if fn_sig.c_variadic {
|
||||||
|
s.push('z');
|
||||||
} else {
|
} else {
|
||||||
if fn_sig.c_variadic {
|
// Empty parameter lists, whether declared as () or conventionally as (void), are
|
||||||
s.push('z');
|
// encoded with a void parameter specifier "v".
|
||||||
} else {
|
s.push('v')
|
||||||
// Empty parameter lists, whether declared as () or conventionally as (void), are
|
|
||||||
// encoded with a void parameter specifier "v".
|
|
||||||
s.push('v')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the "F..E" pair
|
// Close the "F..E" pair
|
||||||
|
@ -381,7 +381,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||||||
let consts = [
|
let consts = [
|
||||||
start.unwrap_or(self.tcx.consts.unit),
|
start.unwrap_or(self.tcx.consts.unit),
|
||||||
end.unwrap_or(self.tcx.consts.unit),
|
end.unwrap_or(self.tcx.consts.unit),
|
||||||
ty::Const::from_bool(self.tcx, include_end).into(),
|
ty::Const::from_bool(self.tcx, include_end),
|
||||||
];
|
];
|
||||||
// HACK: Represent as tuple until we have something better.
|
// HACK: Represent as tuple until we have something better.
|
||||||
// HACK: constants are used in arrays, even if the types don't match.
|
// HACK: constants are used in arrays, even if the types don't match.
|
||||||
|
@ -69,29 +69,27 @@ where
|
|||||||
|
|
||||||
if must_use_stack {
|
if must_use_stack {
|
||||||
arg.make_indirect_byval(None);
|
arg.make_indirect_byval(None);
|
||||||
} else {
|
} else if is_xtensa_aggregate(arg) {
|
||||||
if is_xtensa_aggregate(arg) {
|
// Aggregates which are <= max_size will be passed in
|
||||||
// Aggregates which are <= max_size will be passed in
|
// registers if possible, so coerce to integers.
|
||||||
// registers if possible, so coerce to integers.
|
|
||||||
|
|
||||||
// Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
|
// Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
|
||||||
// is required, and a 2-element `xlen` array if only `xlen` alignment is
|
// is required, and a 2-element `xlen` array if only `xlen` alignment is
|
||||||
// required.
|
// required.
|
||||||
if size <= 32 {
|
if size <= 32 {
|
||||||
arg.cast_to(Reg::i32());
|
arg.cast_to(Reg::i32());
|
||||||
} else {
|
|
||||||
let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
|
|
||||||
let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
|
|
||||||
arg.cast_to(Uniform::new(reg, total));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// All integral types are promoted to `xlen`
|
let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
|
||||||
// width.
|
let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
|
||||||
//
|
arg.cast_to(Uniform::new(reg, total));
|
||||||
// We let the LLVM backend handle integral types >= xlen.
|
}
|
||||||
if size < 32 {
|
} else {
|
||||||
arg.extend_integer_width_to(32);
|
// All integral types are promoted to `xlen`
|
||||||
}
|
// width.
|
||||||
|
//
|
||||||
|
// We let the LLVM backend handle integral types >= xlen.
|
||||||
|
if size < 32 {
|
||||||
|
arg.extend_integer_width_to(32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,12 +351,18 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// On certain targets it makes sense to raise the minimum OS version.
|
// On certain targets it makes sense to raise the minimum OS version.
|
||||||
|
//
|
||||||
|
// This matches what LLVM does, see:
|
||||||
|
// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
|
||||||
let min = match (os, arch, abi) {
|
let min = match (os, arch, abi) {
|
||||||
// Use 11.0 on Aarch64 as that's the earliest version with M1 support.
|
|
||||||
("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
|
("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
|
||||||
("ios", Arch::Arm64e, _) => (14, 0, 0),
|
("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0),
|
||||||
|
("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
|
||||||
|
("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0),
|
||||||
// Mac Catalyst defaults to 13.1 in Clang.
|
// Mac Catalyst defaults to 13.1 in Clang.
|
||||||
("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
|
("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
|
||||||
|
("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0),
|
||||||
|
("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0),
|
||||||
_ => os_min,
|
_ => os_min,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1323,23 +1323,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
label_or_note(span, terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
label_or_note(sp, msg);
|
label_or_note(sp, msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(values) = values
|
||||||
if let Some(values) = values
|
&& let Some((e, f)) = values.ty()
|
||||||
&& let Some((e, f)) = values.ty()
|
&& let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
|
||||||
&& let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
|
{
|
||||||
{
|
let e = self.tcx.erase_regions(e);
|
||||||
let e = self.tcx.erase_regions(e);
|
let f = self.tcx.erase_regions(f);
|
||||||
let f = self.tcx.erase_regions(f);
|
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
|
||||||
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
|
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
|
||||||
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
|
if expected == found {
|
||||||
if expected == found {
|
|
||||||
label_or_note(span, terr.to_string(self.tcx));
|
|
||||||
} else {
|
|
||||||
label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
label_or_note(span, terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
|
} else {
|
||||||
|
label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((expected, found, path)) = expected_found {
|
if let Some((expected, found, path)) = expected_found {
|
||||||
|
@ -3237,16 +3237,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
// then the tuple must be the one containing capture types.
|
// then the tuple must be the one containing capture types.
|
||||||
let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
|
let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
|
||||||
false
|
false
|
||||||
|
} else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
|
||||||
|
let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
|
||||||
|
let nested_ty = parent_trait_ref.skip_binder().self_ty();
|
||||||
|
matches!(nested_ty.kind(), ty::Coroutine(..))
|
||||||
|
|| matches!(nested_ty.kind(), ty::Closure(..))
|
||||||
} else {
|
} else {
|
||||||
if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code {
|
false
|
||||||
let parent_trait_ref =
|
|
||||||
self.resolve_vars_if_possible(data.parent_trait_pred);
|
|
||||||
let nested_ty = parent_trait_ref.skip_binder().self_ty();
|
|
||||||
matches!(nested_ty.kind(), ty::Coroutine(..))
|
|
||||||
|| matches!(nested_ty.kind(), ty::Closure(..))
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !is_upvar_tys_infer_tuple {
|
if !is_upvar_tys_infer_tuple {
|
||||||
|
@ -408,7 +408,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
|||||||
debug!("opt_normalize_projection_type: found error");
|
debug!("opt_normalize_projection_type: found error");
|
||||||
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
|
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
|
||||||
obligations.extend(result.obligations);
|
obligations.extend(result.obligations);
|
||||||
return Ok(Some(result.value.into()));
|
return Ok(Some(result.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +478,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
|
|||||||
}
|
}
|
||||||
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
|
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
|
||||||
obligations.extend(result.obligations);
|
obligations.extend(result.obligations);
|
||||||
Ok(Some(result.value.into()))
|
Ok(Some(result.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,13 +426,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
} else if kind == ty::ClosureKind::FnOnce {
|
} else if kind == ty::ClosureKind::FnOnce {
|
||||||
candidates.vec.push(ClosureCandidate { is_const });
|
candidates.vec.push(ClosureCandidate { is_const });
|
||||||
}
|
}
|
||||||
|
} else if kind == ty::ClosureKind::FnOnce {
|
||||||
|
candidates.vec.push(ClosureCandidate { is_const });
|
||||||
} else {
|
} else {
|
||||||
if kind == ty::ClosureKind::FnOnce {
|
// This stays ambiguous until kind+upvars are determined.
|
||||||
candidates.vec.push(ClosureCandidate { is_const });
|
candidates.ambiguous = true;
|
||||||
} else {
|
|
||||||
// This stays ambiguous until kind+upvars are determined.
|
|
||||||
candidates.ambiguous = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Infer(ty::TyVar(_)) => {
|
ty::Infer(ty::TyVar(_)) => {
|
||||||
@ -513,10 +511,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
// then there's nothing else to check.
|
// then there's nothing else to check.
|
||||||
if let Some(closure_kind) = self_ty.to_opt_closure_kind()
|
if let Some(closure_kind) = self_ty.to_opt_closure_kind()
|
||||||
&& let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
|
&& let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
|
||||||
|
&& closure_kind.extends(goal_kind)
|
||||||
{
|
{
|
||||||
if closure_kind.extends(goal_kind) {
|
candidates.vec.push(AsyncFnKindHelperCandidate);
|
||||||
candidates.vec.push(AsyncFnKindHelperCandidate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1334,16 +1334,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.can_use_global_caches(param_env) {
|
if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
|
||||||
if !trait_pred.has_infer() {
|
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
|
||||||
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
|
// This may overwrite the cache with the same value
|
||||||
// This may overwrite the cache with the same value
|
// FIXME: Due to #50507 this overwrites the different values
|
||||||
// FIXME: Due to #50507 this overwrites the different values
|
// This should be changed to use HashMapExt::insert_same
|
||||||
// This should be changed to use HashMapExt::insert_same
|
// when that is fixed
|
||||||
// when that is fixed
|
self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
|
||||||
self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!(?trait_pred, ?result, "insert_evaluation_cache");
|
debug!(?trait_pred, ?result, "insert_evaluation_cache");
|
||||||
@ -1584,13 +1582,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
if self.can_use_global_caches(param_env) {
|
if self.can_use_global_caches(param_env) {
|
||||||
if let Err(Overflow(OverflowError::Canonical)) = candidate {
|
if let Err(Overflow(OverflowError::Canonical)) = candidate {
|
||||||
// Don't cache overflow globally; we only produce this in certain modes.
|
// Don't cache overflow globally; we only produce this in certain modes.
|
||||||
} else if !pred.has_infer() {
|
} else if !pred.has_infer() && !candidate.has_infer() {
|
||||||
if !candidate.has_infer() {
|
debug!(?pred, ?candidate, "insert_candidate_cache global");
|
||||||
debug!(?pred, ?candidate, "insert_candidate_cache global");
|
// This may overwrite the cache with the same value.
|
||||||
// This may overwrite the cache with the same value.
|
tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
|
||||||
tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1980,10 +1976,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
// impls have to be always applicable, meaning that the only allowed
|
// impls have to be always applicable, meaning that the only allowed
|
||||||
// region constraints may be constraints also present on the default impl.
|
// region constraints may be constraints also present on the default impl.
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
if other.evaluation.must_apply_modulo_regions() {
|
if other.evaluation.must_apply_modulo_regions()
|
||||||
if tcx.specializes((other_def, victim_def)) {
|
&& tcx.specializes((other_def, victim_def))
|
||||||
return DropVictim::Yes;
|
{
|
||||||
}
|
return DropVictim::Yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
|
match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
|
||||||
|
@ -143,10 +143,8 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
|
|||||||
match origin {
|
match origin {
|
||||||
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
|
rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
|
||||||
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
|
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
|
||||||
if !in_assoc_ty {
|
if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
|
||||||
if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ impl<T> [T] {
|
|||||||
if let [first, ..] = self { Some(first) } else { None }
|
if let [first, ..] = self { Some(first) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
|
/// Returns a mutable reference to the first element of the slice, or `None` if it is empty.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1153,6 +1153,21 @@ impl FusedIterator for Ancestors<'_> {}
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Which method works best depends on what kind of situation you're in.
|
/// Which method works best depends on what kind of situation you're in.
|
||||||
|
///
|
||||||
|
/// Note that `PathBuf` does not always sanitize arguments, for example
|
||||||
|
/// [`push`] allows paths built from strings which include separators:
|
||||||
|
///
|
||||||
|
/// use std::path::PathBuf;
|
||||||
|
///
|
||||||
|
/// let mut path = PathBuf::new();
|
||||||
|
///
|
||||||
|
/// path.push(r"C:\");
|
||||||
|
/// path.push("windows");
|
||||||
|
/// path.push(r"..\otherdir");
|
||||||
|
/// path.push("system32");
|
||||||
|
///
|
||||||
|
/// The behaviour of `PathBuf` may be changed to a panic on such inputs
|
||||||
|
/// in the future. [`Extend::extend`] should be used to add multi-part paths.
|
||||||
#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
|
#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct PathBuf {
|
pub struct PathBuf {
|
||||||
@ -1391,6 +1406,9 @@ impl PathBuf {
|
|||||||
/// `file_name`. The new path will be a sibling of the original path.
|
/// `file_name`. The new path will be a sibling of the original path.
|
||||||
/// (That is, it will have the same parent.)
|
/// (That is, it will have the same parent.)
|
||||||
///
|
///
|
||||||
|
/// The argument is not sanitized, so can include separators. This
|
||||||
|
/// behaviour may be changed to a panic in the future.
|
||||||
|
///
|
||||||
/// [`self.file_name`]: Path::file_name
|
/// [`self.file_name`]: Path::file_name
|
||||||
/// [`pop`]: PathBuf::pop
|
/// [`pop`]: PathBuf::pop
|
||||||
///
|
///
|
||||||
@ -1411,6 +1429,12 @@ impl PathBuf {
|
|||||||
///
|
///
|
||||||
/// buf.set_file_name("baz");
|
/// buf.set_file_name("baz");
|
||||||
/// assert!(buf == PathBuf::from("/baz"));
|
/// assert!(buf == PathBuf::from("/baz"));
|
||||||
|
///
|
||||||
|
/// buf.set_file_name("../b/c.txt");
|
||||||
|
/// assert!(buf == PathBuf::from("/../b/c.txt"));
|
||||||
|
///
|
||||||
|
/// buf.set_file_name("baz");
|
||||||
|
/// assert!(buf == PathBuf::from("/../b/baz"));
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
|
pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
|
||||||
|
@ -24,7 +24,7 @@ environment variable.
|
|||||||
|
|
||||||
### OS version
|
### OS version
|
||||||
|
|
||||||
The minimum supported version is iOS 13.1.
|
The minimum supported version is iOS 13.1 on x86 and 14.0 on Aarch64.
|
||||||
|
|
||||||
This can be raised per-binary by changing the deployment target. `rustc`
|
This can be raised per-binary by changing the deployment target. `rustc`
|
||||||
respects the common environment variables used by Xcode to do so, in this
|
respects the common environment variables used by Xcode to do so, in this
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Tier: 3**
|
**Tier: 3**
|
||||||
|
|
||||||
ARM64e iOS (12.0+)
|
ARM64e iOS (14.0+)
|
||||||
|
|
||||||
## Target maintainers
|
## Target maintainers
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||||||
) => {
|
) => {
|
||||||
eq_closure_binder(lb, rb)
|
eq_closure_binder(lb, rb)
|
||||||
&& lc == rc
|
&& lc == rc
|
||||||
&& la.map_or(false, CoroutineKind::is_async) == ra.map_or(false, CoroutineKind::is_async)
|
&& eq_coroutine_kind(*la, *ra)
|
||||||
&& lm == rm
|
&& lm == rm
|
||||||
&& eq_fn_decl(lf, rf)
|
&& eq_fn_decl(lf, rf)
|
||||||
&& eq_expr(le, re)
|
&& eq_expr(le, re)
|
||||||
@ -241,6 +241,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eq_coroutine_kind(a: Option<CoroutineKind>, b: Option<CoroutineKind>) -> bool {
|
||||||
|
match (a, b) {
|
||||||
|
(Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. }))
|
||||||
|
| (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. }))
|
||||||
|
| (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. }))
|
||||||
|
| (None, None) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
|
pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
|
||||||
l.is_placeholder == r.is_placeholder
|
l.is_placeholder == r.is_placeholder
|
||||||
&& eq_id(l.ident, r.ident)
|
&& eq_id(l.ident, r.ident)
|
||||||
|
@ -647,6 +647,12 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
|
|||||||
stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
|
stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-run coverage tests if the `coverage-dump` tool was modified,
|
||||||
|
// because its output format might have changed.
|
||||||
|
if let Some(coverage_dump_path) = &config.coverage_dump_path {
|
||||||
|
stamp.add_path(coverage_dump_path)
|
||||||
|
}
|
||||||
|
|
||||||
stamp.add_dir(&rust_src_dir.join("src/tools/run-make-support"));
|
stamp.add_dir(&rust_src_dir.join("src/tools/run-make-support"));
|
||||||
|
|
||||||
// Compiletest itself.
|
// Compiletest itself.
|
||||||
|
@ -54,6 +54,12 @@ pub fn llvm_dwarfdump() -> LlvmDwarfdump {
|
|||||||
LlvmDwarfdump::new()
|
LlvmDwarfdump::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
|
||||||
|
/// at `$LLVM_BIN_DIR/llvm-pdbutil`.
|
||||||
|
pub fn llvm_pdbutil() -> LlvmPdbutil {
|
||||||
|
LlvmPdbutil::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// A `llvm-readobj` invocation builder.
|
/// A `llvm-readobj` invocation builder.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -55,11 +55,8 @@ fn main() {
|
|||||||
rustc().env(env_var, example_version).run();
|
rustc().env(env_var, example_version).run();
|
||||||
minos("foo.o", example_version);
|
minos("foo.o", example_version);
|
||||||
|
|
||||||
// FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
|
rustc().env_remove(env_var).run();
|
||||||
if !target().contains("macabi") && !target().contains("sim") {
|
minos("foo.o", default_version);
|
||||||
rustc().env_remove(env_var).run();
|
|
||||||
minos("foo.o", default_version);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that version makes it to the linker when linking dylibs.
|
// Test that version makes it to the linker when linking dylibs.
|
||||||
@ -104,8 +101,18 @@ fn main() {
|
|||||||
rustc
|
rustc
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(madsmtm): Doesn't work on watchOS for some reason?
|
// FIXME(madsmtm): Xcode's version of Clang seems to require a minimum
|
||||||
if !target().contains("watchos") {
|
// version of 9.0 on aarch64-apple-watchos for some reason? Which is
|
||||||
|
// odd, because the first Aarch64 watch was Apple Watch Series 4,
|
||||||
|
// which runs on as low as watchOS 5.0.
|
||||||
|
//
|
||||||
|
// You can see Clang's behaviour by running:
|
||||||
|
// ```
|
||||||
|
// echo "int main() { return 0; }" > main.c
|
||||||
|
// xcrun --sdk watchos clang --target=aarch64-apple-watchos main.c
|
||||||
|
// vtool -show a.out
|
||||||
|
// ```
|
||||||
|
if target() != "aarch64-apple-watchos" {
|
||||||
rustc().env(env_var, example_version).run();
|
rustc().env(env_var, example_version).run();
|
||||||
minos("foo", example_version);
|
minos("foo", example_version);
|
||||||
|
|
||||||
@ -146,10 +153,7 @@ fn main() {
|
|||||||
rustc().env(env_var, higher_example_version).run();
|
rustc().env(env_var, higher_example_version).run();
|
||||||
minos("foo.o", higher_example_version);
|
minos("foo.o", higher_example_version);
|
||||||
|
|
||||||
// FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
|
rustc().env_remove(env_var).run();
|
||||||
if !target().contains("macabi") && !target().contains("sim") {
|
minos("foo.o", default_version);
|
||||||
rustc().env_remove(env_var).run();
|
|
||||||
minos("foo.o", default_version);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
4
tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt
Normal file
4
tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CHECK: LF_BUILDINFO
|
||||||
|
CHECK: rustc.exe
|
||||||
|
CHECK: main.rs
|
||||||
|
CHECK: "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-Cmetadata=dc9ef878b0a48666"
|
@ -7,7 +7,7 @@
|
|||||||
//@ only-windows-msvc
|
//@ only-windows-msvc
|
||||||
// Reason: pdb files are unique to this architecture
|
// Reason: pdb files are unique to this architecture
|
||||||
|
|
||||||
use run_make_support::{assert_contains, bstr, env_var, rfs, rustc};
|
use run_make_support::{llvm, rustc};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
rustc()
|
rustc()
|
||||||
@ -17,23 +17,9 @@ fn main() {
|
|||||||
.crate_type("bin")
|
.crate_type("bin")
|
||||||
.metadata("dc9ef878b0a48666")
|
.metadata("dc9ef878b0a48666")
|
||||||
.run();
|
.run();
|
||||||
let tests = [
|
|
||||||
&env_var("RUSTC"),
|
|
||||||
r#""main.rs""#,
|
|
||||||
r#""-g""#,
|
|
||||||
r#""--crate-name""#,
|
|
||||||
r#""my_crate_name""#,
|
|
||||||
r#""--crate-type""#,
|
|
||||||
r#""bin""#,
|
|
||||||
r#""-Cmetadata=dc9ef878b0a48666""#,
|
|
||||||
];
|
|
||||||
for test in tests {
|
|
||||||
assert_pdb_contains(test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_pdb_contains(needle: &str) {
|
let pdbutil_result =
|
||||||
let needle = needle.as_bytes();
|
llvm::llvm_pdbutil().arg("dump").arg("-ids").input("my_crate_name.pdb").run();
|
||||||
use bstr::ByteSlice;
|
|
||||||
assert!(&rfs::read("my_crate_name.pdb").find(needle).is_some());
|
llvm::llvm_filecheck().patterns("filecheck.txt").stdin_buf(pdbutil_result.stdout_utf8()).run();
|
||||||
}
|
}
|
||||||
|
1
tests/run-make/pdb-sobjname/main.rs
Normal file
1
tests/run-make/pdb-sobjname/main.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
fn main() {}
|
20
tests/run-make/pdb-sobjname/rmake.rs
Normal file
20
tests/run-make/pdb-sobjname/rmake.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Check if the pdb file contains an S_OBJNAME entry with the name of the .o file
|
||||||
|
|
||||||
|
// This is because it used to be missing in #96475.
|
||||||
|
// See https://github.com/rust-lang/rust/pull/115704
|
||||||
|
|
||||||
|
//@ only-windows-msvc
|
||||||
|
// Reason: pdb files are unique to this architecture
|
||||||
|
|
||||||
|
use run_make_support::{llvm, rustc};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
rustc().input("main.rs").arg("-g").crate_name("my_great_crate_name").crate_type("bin").run();
|
||||||
|
|
||||||
|
let pdbutil_result = llvm::llvm_pdbutil()
|
||||||
|
.arg("dump")
|
||||||
|
.arg("-symbols")
|
||||||
|
.input("my_great_crate_name.pdb")
|
||||||
|
.run()
|
||||||
|
.assert_stdout_contains_regex("S_OBJNAME.+my_great_crate_name.*\\.o");
|
||||||
|
}
|
12
tests/ui/coroutine/const_gen_fn.rs
Normal file
12
tests/ui/coroutine/const_gen_fn.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//@ edition:2024
|
||||||
|
//@ compile-flags: -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(gen_blocks)]
|
||||||
|
|
||||||
|
const gen fn a() {}
|
||||||
|
//~^ ERROR functions cannot be both `const` and `gen`
|
||||||
|
|
||||||
|
const async gen fn b() {}
|
||||||
|
//~^ ERROR functions cannot be both `const` and `async gen`
|
||||||
|
|
||||||
|
fn main() {}
|
20
tests/ui/coroutine/const_gen_fn.stderr
Normal file
20
tests/ui/coroutine/const_gen_fn.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
error: functions cannot be both `const` and `gen`
|
||||||
|
--> $DIR/const_gen_fn.rs:6:1
|
||||||
|
|
|
||||||
|
LL | const gen fn a() {}
|
||||||
|
| ^^^^^-^^^----------
|
||||||
|
| | |
|
||||||
|
| | `gen` because of this
|
||||||
|
| `const` because of this
|
||||||
|
|
||||||
|
error: functions cannot be both `const` and `async gen`
|
||||||
|
--> $DIR/const_gen_fn.rs:9:1
|
||||||
|
|
|
||||||
|
LL | const async gen fn b() {}
|
||||||
|
| ^^^^^-^^^^^^^^^----------
|
||||||
|
| | |
|
||||||
|
| | `async gen` because of this
|
||||||
|
| `const` because of this
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user