Skip to content

Commit d9c020d

Browse files
committed
Auto merge of rust-lang#14120 - Veykril:castable, r=Veykril
internal: Revert castable expectation and simplify Unfixes rust-lang/rust-analyzer#11571, the PR for that introduced some regressions (tried fixing them but doing what rustc does there specifically does not help, probably because something else affects it as well there)
2 parents a28f536 + 7677f41 commit d9c020d

File tree

5 files changed

+101
-43
lines changed

5 files changed

+101
-43
lines changed

crates/hir-ty/src/infer.rs

+7
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ struct InternedStandardTypes {
219219
unknown: Ty,
220220
bool_: Ty,
221221
unit: Ty,
222+
never: Ty,
222223
}
223224

224225
impl Default for InternedStandardTypes {
@@ -227,6 +228,7 @@ impl Default for InternedStandardTypes {
227228
unknown: TyKind::Error.intern(Interner),
228229
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
229230
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
231+
never: TyKind::Never.intern(Interner),
230232
}
231233
}
232234
}
@@ -1024,6 +1026,7 @@ impl<'a> InferenceContext<'a> {
10241026
pub(crate) enum Expectation {
10251027
None,
10261028
HasType(Ty),
1029+
#[allow(dead_code)]
10271030
Castable(Ty),
10281031
RValueLikeUnsized(Ty),
10291032
}
@@ -1102,6 +1105,10 @@ impl Expectation {
11021105
}
11031106
}
11041107

1108+
fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
1109+
self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
1110+
}
1111+
11051112
/// Comment copied from rustc:
11061113
/// Disregard "castable to" expectations because they
11071114
/// can lead us astray. Consider for example `if cond

crates/hir-ty/src/infer/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl InferenceContext<'_> {
5151
.map(to_chalk_trait_id)
5252
.collect();
5353

54-
let self_ty = TyKind::Error.intern(Interner);
54+
let self_ty = self.result.standard_types.unknown.clone();
5555
let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
5656
for bound in bounds.iter(Interner) {
5757
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
@@ -67,7 +67,7 @@ impl InferenceContext<'_> {
6767
let arg = projection.substitution.as_slice(Interner).get(1)?;
6868
if let Some(subst) = arg.ty(Interner)?.as_tuple() {
6969
let generic_args = subst.as_slice(Interner);
70-
let mut sig_tys = Vec::new();
70+
let mut sig_tys = Vec::with_capacity(generic_args.len() + 1);
7171
for arg in generic_args {
7272
sig_tys.push(arg.ty(Interner)?.clone());
7373
}

crates/hir-ty/src/infer/expr.rs

+36-37
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,15 @@ impl<'a> InferenceContext<'a> {
8787
let expected = &expected.adjust_for_branches(&mut self.table);
8888
self.infer_expr(
8989
condition,
90-
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
90+
&Expectation::HasType(self.result.standard_types.bool_.clone()),
9191
);
9292

9393
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
9494
let mut both_arms_diverge = Diverges::Always;
9595

96-
let result_ty = self.table.new_type_var();
9796
let then_ty = self.infer_expr_inner(then_branch, expected);
9897
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
99-
let mut coerce = CoerceMany::new(result_ty);
98+
let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
10099
coerce.coerce(self, Some(then_branch), &then_ty);
101100
let else_ty = match else_branch {
102101
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
@@ -113,7 +112,7 @@ impl<'a> InferenceContext<'a> {
113112
&Expr::Let { pat, expr } => {
114113
let input_ty = self.infer_expr(expr, &Expectation::none());
115114
self.infer_pat(pat, &input_ty, BindingMode::default());
116-
TyKind::Scalar(Scalar::Bool).intern(Interner)
115+
self.result.standard_types.bool_.clone()
117116
}
118117
Expr::Block { statements, tail, label, id: _ } => {
119118
let old_resolver = mem::replace(
@@ -188,27 +187,29 @@ impl<'a> InferenceContext<'a> {
188187
.intern(Interner)
189188
}
190189
&Expr::Loop { body, label } => {
190+
// FIXME: should be:
191+
// let ty = expected.coercion_target_type(&mut self.table);
191192
let ty = self.table.new_type_var();
192193
let (breaks, ()) =
193194
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
194-
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
195+
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
195196
});
196197

197198
match breaks {
198199
Some(breaks) => {
199200
self.diverges = Diverges::Maybe;
200201
breaks
201202
}
202-
None => TyKind::Never.intern(Interner),
203+
None => self.result.standard_types.never.clone(),
203204
}
204205
}
205206
&Expr::While { condition, body, label } => {
206207
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
207208
this.infer_expr(
208209
condition,
209-
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
210+
&Expectation::HasType(this.result.standard_types.bool_.clone()),
210211
);
211-
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
212+
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
212213
});
213214

214215
// the body may not run, so it diverging doesn't mean we diverge
@@ -224,7 +225,7 @@ impl<'a> InferenceContext<'a> {
224225

225226
self.infer_pat(pat, &pat_ty, BindingMode::default());
226227
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
227-
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
228+
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
228229
});
229230

230231
// the body may not run, so it diverging doesn't mean we diverge
@@ -234,7 +235,7 @@ impl<'a> InferenceContext<'a> {
234235
Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
235236
assert_eq!(args.len(), arg_types.len());
236237

237-
let mut sig_tys = Vec::new();
238+
let mut sig_tys = Vec::with_capacity(arg_types.len() + 1);
238239

239240
// collect explicitly written argument types
240241
for arg_type in arg_types.iter() {
@@ -255,7 +256,8 @@ impl<'a> InferenceContext<'a> {
255256
num_binders: 0,
256257
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
257258
substitution: FnSubst(
258-
Substitution::from_iter(Interner, sig_tys.clone()).shifted_in(Interner),
259+
Substitution::from_iter(Interner, sig_tys.iter().cloned())
260+
.shifted_in(Interner),
259261
),
260262
})
261263
.intern(Interner);
@@ -317,16 +319,16 @@ impl<'a> InferenceContext<'a> {
317319
Expr::Call { callee, args, .. } => {
318320
let callee_ty = self.infer_expr(*callee, &Expectation::none());
319321
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
320-
let mut res = None;
321-
let mut derefed_callee = callee_ty.clone();
322-
// manual loop to be able to access `derefs.table`
323-
while let Some((callee_deref_ty, _)) = derefs.next() {
324-
res = derefs.table.callable_sig(&callee_deref_ty, args.len());
325-
if res.is_some() {
326-
derefed_callee = callee_deref_ty;
327-
break;
322+
let (res, derefed_callee) = 'b: {
323+
// manual loop to be able to access `derefs.table`
324+
while let Some((callee_deref_ty, _)) = derefs.next() {
325+
let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
326+
if res.is_some() {
327+
break 'b (res, callee_deref_ty);
328+
}
328329
}
329-
}
330+
(None, callee_ty.clone())
331+
};
330332
// if the function is unresolved, we use is_varargs=true to
331333
// suppress the arg count diagnostic here
332334
let is_varargs =
@@ -382,12 +384,9 @@ impl<'a> InferenceContext<'a> {
382384
let expected = expected.adjust_for_branches(&mut self.table);
383385

384386
let result_ty = if arms.is_empty() {
385-
TyKind::Never.intern(Interner)
387+
self.result.standard_types.never.clone()
386388
} else {
387-
match &expected {
388-
Expectation::HasType(ty) => ty.clone(),
389-
_ => self.table.new_type_var(),
390-
}
389+
expected.coercion_target_type(&mut self.table)
391390
};
392391
let mut coerce = CoerceMany::new(result_ty);
393392

@@ -400,7 +399,7 @@ impl<'a> InferenceContext<'a> {
400399
if let Some(guard_expr) = arm.guard {
401400
self.infer_expr(
402401
guard_expr,
403-
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
402+
&Expectation::HasType(self.result.standard_types.bool_.clone()),
404403
);
405404
}
406405

@@ -425,7 +424,7 @@ impl<'a> InferenceContext<'a> {
425424
is_break: false,
426425
});
427426
};
428-
TyKind::Never.intern(Interner)
427+
self.result.standard_types.never.clone()
429428
}
430429
Expr::Break { expr, label } => {
431430
let val_ty = if let Some(expr) = *expr {
@@ -439,7 +438,7 @@ impl<'a> InferenceContext<'a> {
439438
// avoiding the borrowck
440439
let mut coerce = mem::replace(
441440
&mut ctxt.coerce,
442-
CoerceMany::new(self.result.standard_types.unknown.clone()),
441+
CoerceMany::new(expected.coercion_target_type(&mut self.table)),
443442
);
444443

445444
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
@@ -457,7 +456,7 @@ impl<'a> InferenceContext<'a> {
457456
});
458457
}
459458
}
460-
TyKind::Never.intern(Interner)
459+
self.result.standard_types.never.clone()
461460
}
462461
Expr::Return { expr } => {
463462
if let Some(expr) = expr {
@@ -466,7 +465,7 @@ impl<'a> InferenceContext<'a> {
466465
let unit = TyBuilder::unit();
467466
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
468467
}
469-
TyKind::Never.intern(Interner)
468+
self.result.standard_types.never.clone()
470469
}
471470
Expr::Yield { expr } => {
472471
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
@@ -479,14 +478,14 @@ impl<'a> InferenceContext<'a> {
479478
resume_ty
480479
} else {
481480
// FIXME: report error (yield expr in non-generator)
482-
TyKind::Error.intern(Interner)
481+
self.result.standard_types.unknown.clone()
483482
}
484483
}
485484
Expr::Yeet { expr } => {
486485
if let &Some(expr) = expr {
487486
self.infer_expr_inner(expr, &Expectation::None);
488487
}
489-
TyKind::Never.intern(Interner)
488+
self.result.standard_types.never.clone()
490489
}
491490
Expr::RecordLit { path, fields, spread, .. } => {
492491
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
@@ -611,8 +610,8 @@ impl<'a> InferenceContext<'a> {
611610
}
612611
Expr::Cast { expr, type_ref } => {
613612
let cast_ty = self.make_ty(type_ref);
614-
let _inner_ty =
615-
self.infer_expr_inner(*expr, &Expectation::Castable(cast_ty.clone()));
613+
// FIXME: propagate the "castable to" expectation
614+
let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
616615
// FIXME check the cast...
617616
cast_ty
618617
}
@@ -829,7 +828,7 @@ impl<'a> InferenceContext<'a> {
829828
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
830829
self.infer_expr(
831830
repeat,
832-
&Expectation::has_type(
831+
&Expectation::HasType(
833832
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
834833
),
835834
);
@@ -852,7 +851,7 @@ impl<'a> InferenceContext<'a> {
852851
TyKind::Array(coerce.complete(), len).intern(Interner)
853852
}
854853
Expr::Literal(lit) => match lit {
855-
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner),
854+
Literal::Bool(..) => self.result.standard_types.bool_.clone(),
856855
Literal::String(..) => {
857856
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
858857
.intern(Interner)
@@ -1148,7 +1147,7 @@ impl<'a> InferenceContext<'a> {
11481147
if let Some(expr) = else_branch {
11491148
self.infer_expr_coerce(
11501149
*expr,
1151-
&Expectation::has_type(Ty::new(Interner, TyKind::Never)),
1150+
&Expectation::HasType(self.result.standard_types.never.clone()),
11521151
);
11531152
}
11541153

crates/hir-ty/src/infer/path.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'a> InferenceContext<'a> {
112112
let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
113113
.fill(|x| {
114114
it.next().unwrap_or_else(|| match x {
115-
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
115+
ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
116116
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
117117
})
118118
})

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

+55-3
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,8 @@ fn func() {
32003200
"#,
32013201
);
32023202
}
3203+
3204+
// FIXME
32033205
#[test]
32043206
fn castable_to() {
32053207
check_infer(
@@ -3224,10 +3226,60 @@ fn func() {
32243226
120..122 '{}': ()
32253227
138..184 '{ ...0]>; }': ()
32263228
148..149 'x': Box<[i32; 0]>
3227-
152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]>
3228-
152..164 'Box::new([])': Box<[i32; 0]>
3229+
152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]>
3230+
152..164 'Box::new([])': Box<[{unknown}; 0]>
32293231
152..181 'Box::n...2; 0]>': Box<[i32; 0]>
3230-
161..163 '[]': [i32; 0]
3232+
161..163 '[]': [{unknown}; 0]
3233+
"#]],
3234+
);
3235+
}
3236+
3237+
#[test]
3238+
fn castable_to1() {
3239+
check_infer(
3240+
r#"
3241+
struct Ark<T>(T);
3242+
impl<T> Ark<T> {
3243+
fn foo(&self) -> *const T {
3244+
&self.0
3245+
}
3246+
}
3247+
fn f<T>(t: Ark<T>) {
3248+
Ark::foo(&t) as *const ();
3249+
}
3250+
"#,
3251+
expect![[r#"
3252+
47..51 'self': &Ark<T>
3253+
65..88 '{ ... }': *const T
3254+
75..82 '&self.0': &T
3255+
76..80 'self': &Ark<T>
3256+
76..82 'self.0': T
3257+
99..100 't': Ark<T>
3258+
110..144 '{ ... (); }': ()
3259+
116..124 'Ark::foo': fn foo<T>(&Ark<T>) -> *const T
3260+
116..128 'Ark::foo(&t)': *const T
3261+
116..141 'Ark::f...nst ()': *const ()
3262+
125..127 '&t': &Ark<T>
3263+
126..127 't': Ark<T>
3264+
"#]],
3265+
);
3266+
}
3267+
3268+
// FIXME
3269+
#[test]
3270+
fn castable_to2() {
3271+
check_infer(
3272+
r#"
3273+
fn func() {
3274+
let x = &0u32 as *const _;
3275+
}
3276+
"#,
3277+
expect![[r#"
3278+
10..44 '{ ...t _; }': ()
3279+
20..21 'x': *const {unknown}
3280+
24..29 '&0u32': &u32
3281+
24..41 '&0u32 ...onst _': *const {unknown}
3282+
25..29 '0u32': u32
32313283
"#]],
32323284
);
32333285
}

0 commit comments

Comments
 (0)