Skip to content

Rollup of 7 pull requests #117402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
351d532
interpret: call caller_location logic the same way codegen does, and …
RalfJung Oct 28, 2023
04fa124
share the track_caller handling within a mir::Body
RalfJung Oct 28, 2023
552abdc
Rename a few remaining references to abort terminator
tmiasko Oct 29, 2023
4b14048
improve and fix x install
onur-ozkan Oct 30, 2023
745c600
Talk about `gen fn` in diagnostics about `gen fn`
oli-obk Oct 30, 2023
bc926f7
Add a custom panic message for resuming `gen` blocks after they panicked
oli-obk Oct 30, 2023
a2486db
Fix missing leading space in suggestion
gurry Oct 30, 2023
82f34fd
Fix #117284, Fix unused variables lint issue for args in macro
chenyukang Oct 30, 2023
8508e65
Fix bad-c-variadic error being emitted multiple times
nicholasbishop Oct 29, 2023
f91b5ce
Explicitly reject const C-variadic functions
nicholasbishop Oct 29, 2023
643bb65
Rollup merge of #117317 - RalfJung:track-caller, r=oli-obk
matthiaskrgr Oct 30, 2023
d992ad8
Rollup merge of #117357 - tmiasko:terminate, r=wesleywiser
matthiaskrgr Oct 30, 2023
b1fa59a
Rollup merge of #117370 - nicholasbishop:bishop-better-c-variadic-err…
matthiaskrgr Oct 30, 2023
c23fa2d
Rollup merge of #117383 - onur-ozkan:fix-x-install, r=albertlarsan68
matthiaskrgr Oct 30, 2023
309bf69
Rollup merge of #117389 - oli-obk:gen_fn, r=compiler-errors
matthiaskrgr Oct 30, 2023
5a36c7e
Rollup merge of #117390 - chenyukang:yukang-fix-117284-unused-macro, …
matthiaskrgr Oct 30, 2023
c6c15d8
Rollup merge of #117395 - gurry:117380-wrong-parent-sugg, r=Nilstrieb
matthiaskrgr Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ ast_passes_const_and_async = functions cannot be both `const` and `async`
.async = `async` because of this
.label = {""}

ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic
.const = `const` because of this
.variadic = C-variadic because of this

ast_passes_const_without_body =
free constant item without body
.suggestion = provide a definition for the constant
Expand Down
37 changes: 30 additions & 7 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,36 @@ impl<'a> AstValidator<'a> {
}
}

/// Reject C-variadic type unless the function is foreign,
/// or free and `unsafe extern "C"` semantically.
/// Reject invalid C-variadic types.
///
/// C-variadics must be:
/// - Non-const
/// - Either foreign, or free and `unsafe extern "C"` semantically
fn check_c_variadic_type(&self, fk: FnKind<'a>) {
let variadic_spans: Vec<_> = fk
.decl()
.inputs
.iter()
.filter(|arg| matches!(arg.ty.kind, TyKind::CVarArgs))
.map(|arg| arg.span)
.collect();

if variadic_spans.is_empty() {
return;
}

if let Some(header) = fk.header() {
if let Const::Yes(const_span) = header.constness {
let mut spans = variadic_spans.clone();
spans.push(const_span);
self.err_handler().emit_err(errors::ConstAndCVariadic {
spans,
const_span,
variadic_spans: variadic_spans.clone(),
});
}
}

match (fk.ctxt(), fk.header()) {
(Some(FnCtxt::Foreign), _) => return,
(Some(FnCtxt::Free), Some(header)) => match header.ext {
Expand All @@ -499,11 +526,7 @@ impl<'a> AstValidator<'a> {
_ => {}
};

for Param { ty, span, .. } in &fk.decl().inputs {
if let TyKind::CVarArgs = ty.kind {
self.err_handler().emit_err(errors::BadCVariadic { span: *span });
}
}
self.err_handler().emit_err(errors::BadCVariadic { span: variadic_spans });
}

fn check_item_named(&self, ident: Ident, kind: &str) {
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub struct ExternItemAscii {
#[diag(ast_passes_bad_c_variadic)]
pub struct BadCVariadic {
#[primary_span]
pub span: Span,
pub span: Vec<Span>,
}

#[derive(Diagnostic)]
Expand Down Expand Up @@ -583,6 +583,17 @@ pub struct ConstAndAsync {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_passes_const_and_c_variadic)]
pub struct ConstAndCVariadic {
#[primary_span]
pub spans: Vec<Span>,
#[label(ast_passes_const)]
pub const_span: Span,
#[label(ast_passes_variadic)]
pub variadic_spans: Vec<Span>,
}

#[derive(Diagnostic)]
#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
pub struct PatternInForeign {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
TerminatorKind::UnwindTerminate(_) => {
if !is_cleanup {
span_mirbug!(self, block_data, "abort on non-cleanup block!")
span_mirbug!(self, block_data, "terminate on non-cleanup block!")
}
}
TerminatorKind::Return => {
Expand Down
46 changes: 5 additions & 41 deletions compiler/rustc_codegen_cranelift/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,47 +430,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
}
}

// Note: must be kept in sync with get_caller_location from cg_ssa
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
use rustc_session::RemapFileNameExt;
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = fx.tcx.const_caller_location((
rustc_span::symbol::Symbol::intern(
&caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(),
),
caller.line as u32,
caller.col_display as u32 + 1,
));
crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
};

// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
// If so, the starting `source_info.span` is in the innermost inlined
// function, and will be replaced with outer callsite spans as long
// as the inlined functions were `#[track_caller]`.
loop {
let scope_data = &self.mir.source_scopes[source_info.scope];

if let Some((callee, callsite_span)) = scope_data.inlined {
// Stop inside the most nested non-`#[track_caller]` function,
// before ever reaching its caller (which is irrelevant).
if !callee.def.requires_caller_location(self.tcx) {
return span_to_caller_location(self, source_info.span);
}
source_info.span = callsite_span;
}

// Skip past all of the parents with `inlined: None`.
match scope_data.inlined_parent_scope {
Some(parent) => source_info.scope = parent,
None => break,
}
}

// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
pub(crate) fn get_caller_location(&mut self, source_info: mir::SourceInfo) -> CValue<'tcx> {
self.mir.caller_location_span(source_info, self.caller_location, self.tcx, |span| {
let const_loc = self.tcx.span_as_caller_location(span);
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
})
}

pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
Expand Down
43 changes: 4 additions & 39 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1449,47 +1449,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn get_caller_location(
&mut self,
bx: &mut Bx,
mut source_info: mir::SourceInfo,
source_info: mir::SourceInfo,
) -> OperandRef<'tcx, Bx::Value> {
let tcx = bx.tcx();

let mut span_to_caller_location = |span: Span| {
use rustc_session::RemapFileNameExt;
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = tcx.const_caller_location((
Symbol::intern(&caller.file.name.for_codegen(self.cx.sess()).to_string_lossy()),
caller.line as u32,
caller.col_display as u32 + 1,
));
self.mir.caller_location_span(source_info, self.caller_location, bx.tcx(), |span: Span| {
let const_loc = bx.tcx().span_as_caller_location(span);
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
};

// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
// If so, the starting `source_info.span` is in the innermost inlined
// function, and will be replaced with outer callsite spans as long
// as the inlined functions were `#[track_caller]`.
loop {
let scope_data = &self.mir.source_scopes[source_info.scope];

if let Some((callee, callsite_span)) = scope_data.inlined {
// Stop inside the most nested non-`#[track_caller]` function,
// before ever reaching its caller (which is irrelevant).
if !callee.def.requires_caller_location(tcx) {
return span_to_caller_location(source_info.span);
}
source_info.span = callsite_span;
}

// Skip past all of the parents with `inlined: None`.
match scope_data.inlined_parent_scope {
Some(parent) => source_info.scope = parent,
None => break,
}
}

// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
self.caller_location.unwrap_or_else(|| span_to_caller_location(source_info.span))
})
}

fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
/// of a function's generic parameter will require knowledge about the bounds on the generic
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
pub(super) fn mk_eval_cx<'mir, 'tcx>(
pub(crate) fn mk_eval_cx<'mir, 'tcx>(
tcx: TyCtxt<'tcx>,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::PointerArithmetic;
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
use std::borrow::Borrow;
use std::hash::Hash;
use std::ops::ControlFlow;
Expand Down Expand Up @@ -181,6 +182,24 @@ impl interpret::MayLeak for ! {
}

impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());

use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
(
Symbol::intern(
&caller
.file
.name
.for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
.to_string_lossy(),
),
u32::try_from(caller.line).unwrap(),
u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
)
}

/// "Intercept" a function call, because we have something special to do for it.
/// All `#[rustc_do_not_const_check]` functions should be hooked here.
/// If this returns `Some` function, which may be `instance` or a different function with
Expand Down
18 changes: 2 additions & 16 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Not in interpret to make sure we do not use private implementation details

use crate::errors::MaxNumNodesInConstErr;
use crate::interpret::{intern_const_alloc_recursive, InternKind, InterpCx, Scalar};
use crate::interpret::InterpCx;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
use rustc_span::source_map::DUMMY_SP;

mod error;
mod eval_queries;
Expand All @@ -20,20 +20,6 @@ pub use fn_queries::*;
pub use machine::*;
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};

pub(crate) fn const_caller_location(
tcx: TyCtxt<'_>,
(file, line, col): (Symbol, u32, u32),
) -> mir::ConstValue<'_> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);

let loc_place = ecx.alloc_caller_location(file, line, col);
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
bug!("intern_const_alloc_recursive should not error in this case")
}
mir::ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
}

// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
const VALTREE_MAX_NODES: usize = 100000;

Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,50 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}

/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
for frame in self.stack().iter().rev() {
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);

// Assert that the frame we look at is actually executing code currently
// (`loc` is `Right` when we are unwinding and the frame does not require cleanup).
let loc = frame.loc.left().unwrap();

// This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
// (such as `box`). Use the normal span by default.
let mut source_info = *frame.body.source_info(loc);

// If this is a `Call` terminator, use the `fn_span` instead.
let block = &frame.body.basic_blocks[loc.block];
if loc.statement_index == block.statements.len() {
debug!(
"find_closest_untracked_caller_location: got terminator {:?} ({:?})",
block.terminator(),
block.terminator().kind,
);
if let mir::TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
source_info.span = fn_span;
}
}

let caller_location = if frame.instance.def.requires_caller_location(*self.tcx) {
// We use `Err(())` as indication that we should continue up the call stack since
// this is a `#[track_caller]` function.
Some(Err(()))
} else {
None
};
if let Ok(span) =
frame.body.caller_location_span(source_info, caller_location, *self.tcx, Ok)
{
return span;
}
}

span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
}

#[inline(always)]
pub fn layout_of_local(
&self,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ use super::{

use crate::fluent_generated as fluent;

mod caller_location;

fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
let size = match kind {
Primitive::Int(integer, _) => integer.size(),
Expand Down Expand Up @@ -130,8 +128,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match intrinsic_name {
sym::caller_location => {
let span = self.find_closest_untracked_caller_location();
let location = self.alloc_caller_location_for_span(span);
self.write_immediate(location.to_ref(self), dest)?;
let val = self.tcx.span_as_caller_location(span);
let val =
self.const_val_to_op(val, self.tcx.caller_location_ty(), Some(dest.layout))?;
self.copy_op(&val, dest, /* allow_transmute */ false)?;
}

sym::min_align_of_val | sym::size_of_val => {
Expand Down
Loading