@@ -9,7 +9,6 @@ use rustc_session::lint;
9
9
use rustc_span:: { Span , Symbol , DUMMY_SP } ;
10
10
use rustc_target:: abi:: { Pointer , VariantIdx } ;
11
11
use rustc_target:: asm:: { InlineAsmReg , InlineAsmRegClass , InlineAsmRegOrRegClass , InlineAsmType } ;
12
- use rustc_trait_selection:: infer:: InferCtxtExt ;
13
12
14
13
use super :: FnCtxt ;
15
14
@@ -98,62 +97,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
98
97
}
99
98
err. emit ( ) ;
100
99
}
100
+ }
101
+
102
+ pub struct InlineAsmCtxt < ' a , ' tcx > {
103
+ tcx : TyCtxt < ' tcx > ,
104
+ param_env : ty:: ParamEnv < ' tcx > ,
105
+ get_operand_ty : Box < dyn Fn ( & ' tcx hir:: Expr < ' tcx > ) -> Ty < ' tcx > + ' a > ,
106
+ }
107
+
108
+ impl < ' a , ' tcx > InlineAsmCtxt < ' a , ' tcx > {
109
+ pub fn new_global_asm ( tcx : TyCtxt < ' tcx > ) -> Self {
110
+ InlineAsmCtxt {
111
+ tcx,
112
+ param_env : ty:: ParamEnv :: empty ( ) ,
113
+ get_operand_ty : Box :: new ( |e| bug ! ( "asm operand in global asm: {e:?}" ) ) ,
114
+ }
115
+ }
116
+
117
+ pub fn new_in_fn (
118
+ tcx : TyCtxt < ' tcx > ,
119
+ param_env : ty:: ParamEnv < ' tcx > ,
120
+ get_operand_ty : impl Fn ( & ' tcx hir:: Expr < ' tcx > ) -> Ty < ' tcx > + ' a ,
121
+ ) -> Self {
122
+ InlineAsmCtxt { tcx, param_env, get_operand_ty : Box :: new ( get_operand_ty) }
123
+ }
101
124
102
125
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
103
126
fn is_thin_ptr_ty ( & self , ty : Ty < ' tcx > ) -> bool {
104
127
// Type still may have region variables, but `Sized` does not depend
105
128
// on those, so just erase them before querying.
106
- if self . tcx . erase_regions ( ty ) . is_sized ( self . tcx . at ( DUMMY_SP ) , self . param_env ) {
129
+ if ty . is_sized ( self . tcx . at ( DUMMY_SP ) , self . param_env ) {
107
130
return true ;
108
131
}
109
132
if let ty:: Foreign ( ..) = ty. kind ( ) {
110
133
return true ;
111
134
}
112
135
false
113
136
}
114
- }
115
-
116
- pub struct InlineAsmCtxt < ' a , ' tcx > {
117
- tcx : TyCtxt < ' tcx > ,
118
- fcx : Option < & ' a FnCtxt < ' a , ' tcx > > ,
119
- }
120
-
121
- impl < ' a , ' tcx > InlineAsmCtxt < ' a , ' tcx > {
122
- pub fn new_global_asm ( tcx : TyCtxt < ' tcx > ) -> Self {
123
- InlineAsmCtxt { tcx, fcx : None }
124
- }
125
-
126
- pub fn new_in_fn ( fcx : & ' a FnCtxt < ' a , ' tcx > ) -> Self {
127
- InlineAsmCtxt { tcx : fcx. tcx , fcx : Some ( fcx) }
128
- }
129
137
130
138
fn check_asm_operand_type (
131
139
& self ,
132
140
idx : usize ,
133
141
reg : InlineAsmRegOrRegClass ,
134
- expr : & hir:: Expr < ' tcx > ,
142
+ expr : & ' tcx hir:: Expr < ' tcx > ,
135
143
template : & [ InlineAsmTemplatePiece ] ,
136
144
is_input : bool ,
137
- tied_input : Option < ( & hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
145
+ tied_input : Option < ( & ' tcx hir:: Expr < ' tcx > , Option < InlineAsmType > ) > ,
138
146
target_features : & FxHashSet < Symbol > ,
139
147
) -> Option < InlineAsmType > {
140
- let fcx = self . fcx . unwrap_or_else ( || span_bug ! ( expr. span , "asm operand for global asm" ) ) ;
141
- // Check the type against the allowed types for inline asm.
142
- let ty = fcx . typeck_results . borrow ( ) . expr_ty_adjusted ( expr) ;
143
- let ty = fcx . resolve_vars_if_possible ( ty ) ;
148
+ let ty = ( self . get_operand_ty ) ( expr) ;
149
+ if ty . has_infer_types_or_consts ( ) {
150
+ bug ! ( "inference variable in asm operand ty: {:?} {:?}" , expr, ty ) ;
151
+ }
144
152
let asm_ty_isize = match self . tcx . sess . target . pointer_width {
145
153
16 => InlineAsmType :: I16 ,
146
154
32 => InlineAsmType :: I32 ,
147
155
64 => InlineAsmType :: I64 ,
148
156
_ => unreachable ! ( ) ,
149
157
} ;
150
158
151
- // Expect types to be fully resolved, no const or type variables.
152
- if ty. has_infer_types_or_consts ( ) {
153
- assert ! ( fcx. is_tainted_by_errors( ) ) ;
154
- return None ;
155
- }
156
-
157
159
let asm_ty = match * ty. kind ( ) {
158
160
// `!` is allowed for input but not for output (issue #87802)
159
161
ty:: Never if is_input => return None ,
@@ -167,7 +169,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
167
169
ty:: Float ( FloatTy :: F32 ) => Some ( InlineAsmType :: F32 ) ,
168
170
ty:: Float ( FloatTy :: F64 ) => Some ( InlineAsmType :: F64 ) ,
169
171
ty:: FnPtr ( _) => Some ( asm_ty_isize) ,
170
- ty:: RawPtr ( ty:: TypeAndMut { ty, mutbl : _ } ) if fcx . is_thin_ptr_ty ( ty) => {
172
+ ty:: RawPtr ( ty:: TypeAndMut { ty, mutbl : _ } ) if self . is_thin_ptr_ty ( ty) => {
171
173
Some ( asm_ty_isize)
172
174
}
173
175
ty:: Adt ( adt, substs) if adt. repr ( ) . simd ( ) => {
@@ -219,7 +221,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
219
221
220
222
// Check that the type implements Copy. The only case where this can
221
223
// possibly fail is for SIMD types which don't #[derive(Copy)].
222
- if !fcx . infcx . type_is_copy_modulo_regions ( fcx . param_env , ty , DUMMY_SP ) {
224
+ if !ty . is_copy_modulo_regions ( self . tcx . at ( expr . span ) , self . param_env ) {
223
225
let msg = "arguments for inline assembly must be copyable" ;
224
226
let mut err = self . tcx . sess . struct_span_err ( expr. span , msg) ;
225
227
err. note ( & format ! ( "`{ty}` does not implement the Copy trait" ) ) ;
@@ -240,8 +242,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
240
242
let msg = "incompatible types for asm inout argument" ;
241
243
let mut err = self . tcx . sess . struct_span_err ( vec ! [ in_expr. span, expr. span] , msg) ;
242
244
243
- let in_expr_ty = fcx. typeck_results . borrow ( ) . expr_ty_adjusted ( in_expr) ;
244
- let in_expr_ty = fcx. resolve_vars_if_possible ( in_expr_ty) ;
245
+ let in_expr_ty = ( self . get_operand_ty ) ( in_expr) ;
245
246
err. span_label ( in_expr. span , & format ! ( "type `{in_expr_ty}`" ) ) ;
246
247
err. span_label ( expr. span , & format ! ( "type `{ty}`" ) ) ;
247
248
err. note (
0 commit comments