Skip to content

Commit cd26032

Browse files
committed
Auto merge of #13546 - Veykril:unsafe-fn-ptr, r=Veykril
Lower unsafety of fn pointer and fn item types
2 parents ad633db + 6f09c72 commit cd26032

File tree

6 files changed

+47
-18
lines changed

6 files changed

+47
-18
lines changed

crates/hir-def/src/pretty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,12 @@ pub(crate) fn print_type_ref(type_ref: &TypeRef, buf: &mut dyn Write) -> fmt::Re
143143
print_type_ref(elem, buf)?;
144144
write!(buf, "]")?;
145145
}
146-
TypeRef::Fn(args_and_ret, varargs) => {
146+
TypeRef::Fn(args_and_ret, varargs, is_unsafe) => {
147147
let ((_, return_type), args) =
148148
args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
149+
if *is_unsafe {
150+
write!(buf, "unsafe ")?;
151+
}
149152
write!(buf, "fn(")?;
150153
for (i, (_, typeref)) in args.iter().enumerate() {
151154
if i != 0 {

crates/hir-def/src/type_ref.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub enum TypeRef {
119119
Array(Box<TypeRef>, ConstScalarOrPath),
120120
Slice(Box<TypeRef>),
121121
/// A fn pointer. Last element of the vector is the return type.
122-
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/),
122+
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
123123
ImplTrait(Vec<Interned<TypeBound>>),
124124
DynTrait(Vec<Interned<TypeBound>>),
125125
Macro(AstId<ast::MacroCall>),
@@ -229,7 +229,7 @@ impl TypeRef {
229229
Vec::new()
230230
};
231231
params.push((None, ret_ty));
232-
TypeRef::Fn(params, is_varargs)
232+
TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some())
233233
}
234234
// for types are close enough for our purposes to the inner type for now...
235235
ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -263,7 +263,7 @@ impl TypeRef {
263263
fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
264264
f(type_ref);
265265
match type_ref {
266-
TypeRef::Fn(params, _) => {
266+
TypeRef::Fn(params, _, _) => {
267267
params.iter().for_each(|(_, param_type)| go(param_type, f))
268268
}
269269
TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),

crates/hir-ty/src/display.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,11 @@ impl HirDisplay for TypeRef {
11871187
inner.hir_fmt(f)?;
11881188
write!(f, "]")?;
11891189
}
1190-
TypeRef::Fn(parameters, is_varargs) => {
1190+
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
11911191
// FIXME: Function pointer qualifiers.
1192+
if is_unsafe {
1193+
write!(f, "unsafe ")?;
1194+
}
11921195
write!(f, "fn(")?;
11931196
if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
11941197
for index in 0..function_parameters.len() {
@@ -1203,7 +1206,7 @@ impl HirDisplay for TypeRef {
12031206
write!(f, ", ")?;
12041207
}
12051208
}
1206-
if *is_varargs {
1209+
if is_varargs {
12071210
write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
12081211
}
12091212
write!(f, ")")?;

crates/hir-ty/src/lib.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
210210
pub struct CallableSig {
211211
params_and_return: Arc<[Ty]>,
212212
is_varargs: bool,
213+
safety: Safety,
213214
}
214215

215216
has_interner!(CallableSig);
@@ -218,9 +219,14 @@ has_interner!(CallableSig);
218219
pub type PolyFnSig = Binders<CallableSig>;
219220

220221
impl CallableSig {
221-
pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
222+
pub fn from_params_and_return(
223+
mut params: Vec<Ty>,
224+
ret: Ty,
225+
is_varargs: bool,
226+
safety: Safety,
227+
) -> CallableSig {
222228
params.push(ret);
223-
CallableSig { params_and_return: params.into(), is_varargs }
229+
CallableSig { params_and_return: params.into(), is_varargs, safety }
224230
}
225231

226232
pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
@@ -237,13 +243,14 @@ impl CallableSig {
237243
.map(|arg| arg.assert_ty_ref(Interner).clone())
238244
.collect(),
239245
is_varargs: fn_ptr.sig.variadic,
246+
safety: fn_ptr.sig.safety,
240247
}
241248
}
242249

243250
pub fn to_fn_ptr(&self) -> FnPointer {
244251
FnPointer {
245252
num_binders: 0,
246-
sig: FnSig { abi: (), safety: Safety::Safe, variadic: self.is_varargs },
253+
sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs },
247254
substitution: FnSubst(Substitution::from_iter(
248255
Interner,
249256
self.params_and_return.iter().cloned(),
@@ -268,7 +275,11 @@ impl TypeFoldable<Interner> for CallableSig {
268275
) -> Result<Self, E> {
269276
let vec = self.params_and_return.to_vec();
270277
let folded = vec.try_fold_with(folder, outer_binder)?;
271-
Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
278+
Ok(CallableSig {
279+
params_and_return: folded.into(),
280+
is_varargs: self.is_varargs,
281+
safety: self.safety,
282+
})
272283
}
273284
}
274285

@@ -573,5 +584,5 @@ pub fn callable_sig_from_fnonce(
573584

574585
let ret_ty = db.normalize_projection(projection, env);
575586

576-
Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false))
587+
Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false, Safety::Safe))
577588
}

crates/hir-ty/src/lower.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,13 +227,17 @@ impl<'a> TyLoweringContext<'a> {
227227
.intern(Interner)
228228
}
229229
TypeRef::Placeholder => TyKind::Error.intern(Interner),
230-
TypeRef::Fn(params, is_varargs) => {
230+
&TypeRef::Fn(ref params, variadic, is_unsafe) => {
231231
let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
232232
Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
233233
});
234234
TyKind::Function(FnPointer {
235235
num_binders: 0, // FIXME lower `for<'a> fn()` correctly
236-
sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
236+
sig: FnSig {
237+
abi: (),
238+
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
239+
variadic,
240+
},
237241
substitution: FnSubst(substs),
238242
})
239243
.intern(Interner)
@@ -1573,7 +1577,12 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
15731577
.with_type_param_mode(ParamLoweringMode::Variable);
15741578
let ret = ctx_ret.lower_ty(&data.ret_type);
15751579
let generics = generics(db.upcast(), def.into());
1576-
let sig = CallableSig::from_params_and_return(params, ret, data.is_varargs());
1580+
let sig = CallableSig::from_params_and_return(
1581+
params,
1582+
ret,
1583+
data.is_varargs(),
1584+
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
1585+
);
15771586
make_binders(db, &generics, sig)
15781587
}
15791588

@@ -1617,7 +1626,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
16171626
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
16181627
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
16191628
let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
1620-
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1629+
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
16211630
}
16221631

16231632
/// Build the type of a tuple struct constructor.
@@ -1644,7 +1653,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
16441653
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
16451654
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
16461655
let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
1647-
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1656+
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
16481657
}
16491658

16501659
/// Build the type of a tuple enum variant constructor.

crates/hir-ty/src/tests/coercion.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ fn test() {
390390
let f: fn(u32) -> isize = foo;
391391
// ^^^ adjustments: Pointer(ReifyFnPointer)
392392
let f: unsafe fn(u32) -> isize = foo;
393-
// ^^^ adjustments: Pointer(ReifyFnPointer)
393+
// ^^^ adjustments: Pointer(ReifyFnPointer), Pointer(UnsafeFnPointer)
394394
}",
395395
);
396396
}
@@ -421,7 +421,10 @@ fn coerce_closure_to_fn_ptr() {
421421
check_no_mismatches(
422422
r"
423423
fn test() {
424-
let f: fn(u32) -> isize = |x| { 1 };
424+
let f: fn(u32) -> u32 = |x| x;
425+
// ^^^^^ adjustments: Pointer(ClosureFnPointer(Safe))
426+
let f: unsafe fn(u32) -> u32 = |x| x;
427+
// ^^^^^ adjustments: Pointer(ClosureFnPointer(Unsafe))
425428
}",
426429
);
427430
}

0 commit comments

Comments
 (0)