Skip to content

Move inline asm check to typeck, properly handle aliases #140302

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3794,7 +3794,6 @@ dependencies = [
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"smallvec",
"tracing",
Expand Down Expand Up @@ -3833,6 +3832,7 @@ dependencies = [
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"smallvec",
"tracing",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_analysis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,6 @@ hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
hir_analysis_register_type_unstable =
type `{$ty}` cannot be used with this register class in stable
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
hir_analysis_return_type_notation_equality_bound =
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ mod check;
mod compare_impl_item;
mod entry;
pub mod intrinsic;
pub mod intrinsicck;
mod region;
pub mod wfcheck;

Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1675,14 +1675,6 @@ pub(crate) struct CmseEntryGeneric {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_register_type_unstable)]
pub(crate) struct RegisterTypeUnstable<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}

#[derive(LintDiagnostic)]
#[diag(hir_analysis_supertrait_item_shadowing)]
pub(crate) struct SupertraitItemShadowing {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len ->
.help = use `transmute` if you're sure this is sound
.label = unsupported cast
hir_typeck_register_type_unstable =
type `{$ty}` cannot be used with this register class in stable
hir_typeck_remove_semi_for_coerce = you might have meant to return the `match` expression
hir_typeck_remove_semi_for_coerce_expr = this could be implicitly returned but it is a statement, not a tail expression
hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this return type
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -963,3 +963,11 @@ pub(crate) enum SupertraitItemShadowee {
traits: DiagSymbolList,
},
}

#[derive(Diagnostic)]
#[diag(hir_typeck_register_type_unstable)]
pub(crate) struct RegisterTypeUnstable<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}
10 changes: 2 additions & 8 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{ExprKind, HirId, Node, QPath};
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
use rustc_hir_analysis::check::potentially_plural_count;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_index::IndexVec;
Expand All @@ -33,6 +32,7 @@ use crate::errors::SuggestPtrNullMut;
use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
use crate::fn_ctxt::infer::FnCall;
use crate::gather_locals::Declaration;
use crate::inline_asm::InlineAsmCtxt;
use crate::method::MethodCallee;
use crate::method::probe::IsSuggestion;
use crate::method::probe::Mode::MethodCall;
Expand Down Expand Up @@ -98,13 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
for (asm, hir_id) in deferred_asm_checks.drain(..) {
let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
InlineAsmCtxt::new(
enclosing_id,
&self.infcx,
self.typing_env(self.param_env),
&*self.typeck_results.borrow(),
)
.check_asm(asm);
InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,22 @@ use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::InferCtxt;
use rustc_middle::bug;
use rustc_middle::ty::{
self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, TypeckResults, UintTy,
};
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, sym};
use rustc_span::{Span, Symbol, sym};
use rustc_target::asm::{
InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
};
use rustc_trait_selection::infer::InferCtxtExt;

use crate::FnCtxt;
use crate::errors::RegisterTypeUnstable;

pub struct InlineAsmCtxt<'a, 'tcx> {
typing_env: ty::TypingEnv<'tcx>,
pub(crate) struct InlineAsmCtxt<'a, 'tcx> {
target_features: &'tcx FxIndexSet<Symbol>,
infcx: &'a InferCtxt<'tcx>,
typeck_results: &'a TypeckResults<'tcx>,
fcx: &'a FnCtxt<'a, 'tcx>,
}

enum NonAsmTypeReason<'tcx> {
Expand All @@ -33,27 +30,17 @@ enum NonAsmTypeReason<'tcx> {
}

impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
pub fn new(
def_id: LocalDefId,
infcx: &'a InferCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
typeck_results: &'a TypeckResults<'tcx>,
) -> Self {
InlineAsmCtxt {
typing_env,
target_features: infcx.tcx.asm_target_features(def_id),
infcx,
typeck_results,
}
pub(crate) fn new(fcx: &'a FnCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
InlineAsmCtxt { target_features: fcx.tcx.asm_target_features(def_id), fcx }
}

fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
self.fcx.tcx
}

fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> {
let ty = self.typeck_results.expr_ty_adjusted(expr);
let ty = self.infcx.resolve_vars_if_possible(ty);
let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.fcx.try_structurally_resolve_type(expr.span, ty);
if ty.has_non_region_infer() {
Ty::new_misc_error(self.tcx())
} else {
Expand All @@ -62,19 +49,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}

// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
fn is_thin_ptr_ty(&self, span: Span, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying.
if ty.is_sized(self.tcx(), self.typing_env) {
if self.fcx.type_is_sized_modulo_regions(self.fcx.param_env, ty) {
return true;
}
if let ty::Foreign(..) = ty.kind() {
if let ty::Foreign(..) = self.fcx.try_structurally_resolve_type(span, ty).kind() {
return true;
}
false
}

fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> {
fn get_asm_ty(
&self,
span: Span,
ty: Ty<'tcx>,
) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> {
let asm_ty_isize = match self.tcx().sess.target.pointer_width {
16 => InlineAsmType::I16,
32 => InlineAsmType::I32,
Expand All @@ -95,7 +86,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128),
ty::FnPtr(..) => Ok(asm_ty_isize),
ty::RawPtr(elem_ty, _) => {
if self.is_thin_ptr_ty(elem_ty) {
if self.is_thin_ptr_ty(span, elem_ty) {
Ok(asm_ty_isize)
} else {
Err(NonAsmTypeReason::NotSizedPtr(ty))
Expand All @@ -109,11 +100,20 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let field = &fields[FieldIdx::ZERO];
let elem_ty = field.ty(self.tcx(), args);

let (size, ty) = match elem_ty.kind() {
let (size, ty) = match *elem_ty.kind() {
ty::Array(ty, len) => {
let len = self.tcx().normalize_erasing_regions(self.typing_env, *len);
// FIXME: `try_structurally_resolve_const` doesn't eval consts
// in the old solver.
let len = if self.fcx.next_trait_solver() {
self.fcx.try_structurally_resolve_const(span, len)
} else {
self.fcx.tcx.normalize_erasing_regions(
self.fcx.typing_env(self.fcx.param_env),
len,
)
};
if let Some(len) = len.try_to_target_usize(self.tcx()) {
(len, *ty)
(len, ty)
} else {
return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
field.did, len,
Expand Down Expand Up @@ -183,17 +183,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
);
let fields = &ty.non_enum_variant().fields;
let ty = fields[FieldIdx::ZERO].ty(self.tcx(), args);
self.get_asm_ty(ty)
self.get_asm_ty(expr.span, ty)
}
_ => self.get_asm_ty(ty),
_ => self.get_asm_ty(expr.span, ty),
};
let asm_ty = match asm_ty {
Ok(asm_ty) => asm_ty,
Err(reason) => {
match reason {
NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => {
let msg = format!("cannot evaluate SIMD vector length `{len}`");
self.infcx
self.fcx
.dcx()
.struct_span_err(self.tcx().def_span(did), msg)
.with_span_note(
Expand All @@ -204,7 +204,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
NonAsmTypeReason::Invalid(ty) => {
let msg = format!("cannot use value of type `{ty}` for inline assembly");
self.infcx.dcx().struct_span_err(expr.span, msg).with_note(
self.fcx.dcx().struct_span_err(expr.span, msg).with_note(
"only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly",
).emit();
Expand All @@ -213,7 +213,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let msg = format!(
"cannot use value of unsized pointer type `{ty}` for inline assembly"
);
self.infcx
self.fcx
.dcx()
.struct_span_err(expr.span, msg)
.with_note("only sized pointers can be used in inline assembly")
Expand All @@ -223,7 +223,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let msg = format!(
"cannot use SIMD vector with element type `{ty}` for inline assembly"
);
self.infcx.dcx()
self.fcx.dcx()
.struct_span_err(self.tcx().def_span(did), msg).with_span_note(
expr.span,
"only integers, floats, SIMD vectors, pointers and function pointers \
Expand All @@ -232,7 +232,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
NonAsmTypeReason::EmptySIMDArray(ty) => {
let msg = format!("use of empty SIMD vector `{ty}`");
self.infcx.dcx().struct_span_err(expr.span, msg).emit();
self.fcx.dcx().struct_span_err(expr.span, msg).emit();
}
}
return None;
Expand All @@ -241,9 +241,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {

// Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)].
if !self.tcx().type_is_copy_modulo_regions(self.typing_env, ty) {
if !self.fcx.type_is_copy_modulo_regions(self.fcx.param_env, ty) {
let msg = "arguments for inline assembly must be copyable";
self.infcx
self.fcx
.dcx()
.struct_span_err(expr.span, msg)
.with_note(format!("`{ty}` does not implement the Copy trait"))
Expand All @@ -263,7 +263,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if in_asm_ty != asm_ty {
let msg = "incompatible types for asm inout argument";
let in_expr_ty = self.expr_ty(in_expr);
self.infcx
self.fcx
.dcx()
.struct_span_err(vec![in_expr.span, expr.span], msg)
.with_span_label(in_expr.span, format!("type `{in_expr_ty}`"))
Expand Down Expand Up @@ -296,7 +296,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
)
} else {
let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.infcx.dcx().struct_span_err(expr.span, msg);
let mut err = self.fcx.dcx().struct_span_err(expr.span, msg);
let supported_tys: Vec<_> =
supported_tys.iter().map(|(t, _)| t.to_string()).collect();
err.note(format!(
Expand Down Expand Up @@ -326,7 +326,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if let Some(feature) = feature {
if !self.target_features.contains(feature) {
let msg = format!("`{feature}` target feature is not enabled");
self.infcx
self.fcx
.dcx()
.struct_span_err(expr.span, msg)
.with_note(format!(
Expand Down Expand Up @@ -384,9 +384,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
Some(asm_ty)
}

pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
pub(crate) fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
let Some(asm_arch) = self.tcx().sess.asm_arch else {
self.infcx.dcx().delayed_bug("target architecture does not support asm");
self.fcx.dcx().delayed_bug("target architecture does not support asm");
return;
};
let allow_experimental_reg = self.tcx().features().asm_experimental_reg();
Expand Down Expand Up @@ -418,7 +418,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
op.is_clobber(),
) {
let msg = format!("cannot use register `{}`: {}", reg.name(), msg);
self.infcx.dcx().span_err(op_sp, msg);
self.fcx.dcx().span_err(op_sp, msg);
continue;
}
}
Expand Down Expand Up @@ -458,7 +458,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
reg_class.name(),
feature
);
self.infcx.dcx().span_err(op_sp, msg);
self.fcx.dcx().span_err(op_sp, msg);
// register isn't enabled, don't do more checks
continue;
}
Expand All @@ -472,7 +472,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
.intersperse(", ")
.collect::<String>(),
);
self.infcx.dcx().span_err(op_sp, msg);
self.fcx.dcx().span_err(op_sp, msg);
// register isn't enabled, don't do more checks
continue;
}
Expand Down Expand Up @@ -512,7 +512,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Error(_) => {}
_ if ty.is_integral() => {}
_ => {
self.infcx
self.fcx
.dcx()
.struct_span_err(op_sp, "invalid type for `const` operand")
.with_span_label(
Expand All @@ -531,7 +531,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::FnDef(..) => {}
ty::Error(_) => {}
_ => {
self.infcx
self.fcx
.dcx()
.struct_span_err(op_sp, "invalid `sym` operand")
.with_span_label(
Expand Down
Loading
Loading