Skip to content

Commit 9779526

Browse files
committed
Record coercion adjustments
1 parent e44c56b commit 9779526

File tree

9 files changed

+340
-87
lines changed

9 files changed

+340
-87
lines changed

crates/hir_ty/src/diagnostics/match_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'a> PatCtxt<'a> {
109109
self.infer.pat_adjustments.get(&pat).map(|it| &**it).unwrap_or_default().iter().rev().fold(
110110
unadjusted_pat,
111111
|subpattern, ref_ty| Pat {
112-
ty: ref_ty.clone(),
112+
ty: ref_ty.target.clone(),
113113
kind: Box::new(PatKind::Deref { subpattern }),
114114
},
115115
)

crates/hir_ty/src/infer.rs

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use std::ops::Index;
1717
use std::sync::Arc;
1818

19-
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
19+
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety};
2020
use hir_def::{
2121
body::Body,
2222
data::{ConstData, FunctionData, StaticData},
@@ -103,12 +103,20 @@ impl Default for BindingMode {
103103
}
104104

105105
#[derive(Debug)]
106-
pub(crate) struct InferOk {
106+
pub(crate) struct InferOk<T> {
107+
value: T,
107108
goals: Vec<InEnvironment<Goal>>,
108109
}
110+
111+
impl<T> InferOk<T> {
112+
fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> {
113+
InferOk { value: f(self.value), goals: self.goals }
114+
}
115+
}
116+
109117
#[derive(Debug)]
110118
pub(crate) struct TypeError;
111-
pub(crate) type InferResult = Result<InferOk, TypeError>;
119+
pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
112120

113121
#[derive(Debug, PartialEq, Eq, Clone)]
114122
pub enum InferenceDiagnostic {
@@ -134,6 +142,78 @@ impl Default for InternedStandardTypes {
134142
}
135143
}
136144

145+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
146+
pub struct Adjustment {
147+
pub kind: Adjust,
148+
pub target: Ty,
149+
}
150+
151+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
152+
pub enum Adjust {
153+
/// Go from ! to any type.
154+
NeverToAny,
155+
156+
/// Dereference once, producing a place.
157+
Deref(Option<OverloadedDeref>),
158+
159+
/// Take the address and produce either a `&` or `*` pointer.
160+
Borrow(AutoBorrow),
161+
162+
Pointer(PointerCast),
163+
}
164+
165+
// impl fmt::Display for Adjust {
166+
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167+
// match self {
168+
// Adjust::NeverToAny => write!(f, "NeverToAny"),
169+
// Adjust::Deref(_) => write!(f, "Deref"), // FIXME
170+
// Adjust::Borrow(AutoBorrow::Ref(mt)) => write!(f, "BorrowRef{:?}", mt),
171+
// Adjust::Borrow(AutoBorrow::RawPtr(mt)) => write!(f, "BorrowRawPtr{:?}", mt),
172+
// Adjust::Pointer(cast) => write!(f, "PtrCast{:?}", cast),
173+
// }
174+
// }
175+
// }
176+
177+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
178+
pub struct OverloadedDeref(Mutability);
179+
180+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
181+
pub enum AutoBorrow {
182+
Ref(Mutability),
183+
RawPtr(Mutability),
184+
}
185+
186+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
187+
pub enum PointerCast {
188+
/// Go from a fn-item type to a fn-pointer type.
189+
ReifyFnPointer,
190+
191+
/// Go from a safe fn pointer to an unsafe fn pointer.
192+
UnsafeFnPointer,
193+
194+
/// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
195+
/// It cannot convert a closure that requires unsafe.
196+
ClosureFnPointer(Safety),
197+
198+
/// Go from a mut raw pointer to a const raw pointer.
199+
MutToConstPointer,
200+
201+
/// Go from `*const [T; N]` to `*const T`
202+
ArrayToPointer,
203+
204+
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
205+
/// `&[T]`. Note that the source could be a thin or fat pointer.
206+
/// This will do things like convert thin pointers to fat
207+
/// pointers, or convert structs containing thin pointers to
208+
/// structs containing fat pointers, or convert between fat
209+
/// pointers. We don't store the details of how the transform is
210+
/// done (in fact, we don't know that, because it might depend on
211+
/// the precise type parameters). We just store the target
212+
/// type. Codegen backends and miri figure out what has to be done
213+
/// based on the precise source/target type at hand.
214+
Unsize,
215+
}
216+
137217
/// The result of type inference: A mapping from expressions and patterns to types.
138218
#[derive(Clone, PartialEq, Eq, Debug, Default)]
139219
pub struct InferenceResult {
@@ -156,7 +236,8 @@ pub struct InferenceResult {
156236
/// Interned Unknown to return references to.
157237
standard_types: InternedStandardTypes,
158238
/// Stores the types which were implicitly dereferenced in pattern binding modes.
159-
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
239+
pub pat_adjustments: FxHashMap<PatId, Vec<Adjustment>>,
240+
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
160241
}
161242

162243
impl InferenceResult {
@@ -303,6 +384,10 @@ impl<'a> InferenceContext<'a> {
303384
self.result.type_of_expr.insert(expr, ty);
304385
}
305386

387+
fn write_expr_adj(&mut self, expr: ExprId, adjustments: Vec<Adjustment>) {
388+
self.result.expr_adjustments.insert(expr, adjustments);
389+
}
390+
306391
fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) {
307392
self.result.method_resolutions.insert(expr, (func, subst));
308393
}

crates/hir_ty/src/infer/closure.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Inference of closure parameter types based on the closure's expected type.
22
33
use chalk_ir::{cast::Cast, AliasTy, FnSubst, WhereClause};
4-
use hir_def::HasModule;
4+
use hir_def::{expr::ExprId, HasModule};
55
use smallvec::SmallVec;
66

77
use crate::{
@@ -14,6 +14,7 @@ use super::{Expectation, InferenceContext};
1414
impl InferenceContext<'_> {
1515
pub(super) fn deduce_closure_type_from_expectations(
1616
&mut self,
17+
closure_expr: ExprId,
1718
closure_ty: &Ty,
1819
sig_ty: &Ty,
1920
expectation: &Expectation,
@@ -24,8 +25,9 @@ impl InferenceContext<'_> {
2425
};
2526

2627
// Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
27-
self.coerce(closure_ty, &expected_ty);
28-
28+
if let Ok(res) = self.coerce(closure_ty, &expected_ty) {
29+
self.write_expr_adj(closure_expr, res.value.0);
30+
}
2931
// Deduction based on the expected `dyn Fn` is done separately.
3032
if let TyKind::Dyn(dyn_ty) = expected_ty.kind(&Interner) {
3133
if let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty) {

0 commit comments

Comments
 (0)