Rollup merge of #137686 - nbdd0121:asm_const, r=compiler-errors
Handle asm const similar to inline const Previously, asm consts are handled similar to anon consts rather than inline consts. Anon consts are not good at dealing with lifetimes, because `type_of` has lifetimes erased already. Inline consts can deal with lifetimes because they live in an outer typeck context. And since `global_asm!` lacks an outer typeck context, we have implemented asm consts with anon consts while they're in fact more similar to inline consts. This was changed in #137180, and this means that handling asm consts as inline consts are possible. While as `@compiler-errors` pointed out, `const` currently can't be used with any types with lifetime, this is about to change if #128464 is implemented. This PR is a preparatory PR for that feature. As an unintentional side effect, fix #117877. cc `@Amanieu` r? `@compiler-errors`
This commit is contained in:
commit
174bbfb369
18 changed files with 132 additions and 99 deletions
|
@ -1,5 +1,3 @@
|
|||
use std::assert_matches::debug_assert_matches;
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
|
@ -21,6 +19,7 @@ pub struct InlineAsmCtxt<'a, 'tcx: 'a> {
|
|||
typing_env: ty::TypingEnv<'tcx>,
|
||||
target_features: &'tcx FxIndexSet<Symbol>,
|
||||
expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
|
||||
node_ty: Box<dyn Fn(hir::HirId) -> Ty<'tcx> + 'a>,
|
||||
}
|
||||
|
||||
enum NonAsmTypeReason<'tcx> {
|
||||
|
@ -35,13 +34,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
|
||||
expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
|
||||
node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a,
|
||||
) -> Self {
|
||||
InlineAsmCtxt {
|
||||
tcx,
|
||||
typing_env,
|
||||
target_features: tcx.asm_target_features(def_id),
|
||||
expr_ty: Box::new(get_operand_ty),
|
||||
expr_ty: Box::new(expr_ty),
|
||||
node_ty: Box::new(node_ty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +50,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
(self.expr_ty)(expr)
|
||||
}
|
||||
|
||||
fn node_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
|
||||
(self.node_ty)(hir_id)
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
|
||||
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
|
||||
// Type still may have region variables, but `Sized` does not depend
|
||||
|
@ -487,12 +492,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
// Typeck has checked that Const operands are integers.
|
||||
hir::InlineAsmOperand::Const { anon_const } => {
|
||||
debug_assert_matches!(
|
||||
self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
|
||||
ty::Error(_) | ty::Int(_) | ty::Uint(_)
|
||||
);
|
||||
let ty = self.node_ty(anon_const.hir_id);
|
||||
match ty.kind() {
|
||||
ty::Error(_) => {}
|
||||
_ if ty.is_integral() => {}
|
||||
_ => {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(op_sp, "invalid type for `const` operand")
|
||||
.with_span_label(
|
||||
self.tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.with_help("`const` operands must be of an integer type")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Typeck has checked that SymFn refers to a function.
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
|
|
|
@ -186,17 +186,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
// Exclude `GlobalAsm` here which cannot have generics.
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const } => {
|
||||
anon_const.hir_id == hir_id
|
||||
}
|
||||
_ => false,
|
||||
}) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
Node::TyPat(_) => Some(parent_did),
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_middle::query::plumbing::CyclePlaceholder;
|
|||
use rustc_middle::ty::fold::fold_regions;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span};
|
||||
|
||||
|
@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
|
|||
let parent_node_id = tcx.parent_hir_id(hir_id);
|
||||
let parent_node = tcx.hir_node(parent_node_id);
|
||||
|
||||
let find_const = |&(op, op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
|
||||
Some((anon_const, op_sp))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match parent_node {
|
||||
// Anon consts "inside" the type system.
|
||||
Node::ConstArg(&ConstArg {
|
||||
|
@ -50,31 +43,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
|
|||
..
|
||||
}) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
|
||||
|
||||
// Anon consts outside the type system.
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
|
||||
if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
|
||||
{
|
||||
let ty = tcx.typeck(def_id).node_type(hir_id);
|
||||
|
||||
match ty.kind() {
|
||||
ty::Error(_) => ty,
|
||||
ty::Int(_) | ty::Uint(_) => ty,
|
||||
_ => {
|
||||
let guar = tcx
|
||||
.dcx()
|
||||
.struct_span_err(op_sp, "invalid type for `const` operand")
|
||||
.with_span_label(
|
||||
tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.with_help("`const` operands must be of an integer type")
|
||||
.emit();
|
||||
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
}
|
||||
}
|
||||
Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
|
||||
tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue