mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
internal: Revert castable expectation and simplify
This commit is contained in:
parent
8f5deb4ff2
commit
79492cb8ae
@ -219,6 +219,7 @@ struct InternedStandardTypes {
|
|||||||
unknown: Ty,
|
unknown: Ty,
|
||||||
bool_: Ty,
|
bool_: Ty,
|
||||||
unit: Ty,
|
unit: Ty,
|
||||||
|
never: Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InternedStandardTypes {
|
impl Default for InternedStandardTypes {
|
||||||
@ -227,6 +228,7 @@ impl Default for InternedStandardTypes {
|
|||||||
unknown: TyKind::Error.intern(Interner),
|
unknown: TyKind::Error.intern(Interner),
|
||||||
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
|
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
|
||||||
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
|
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
|
||||||
|
never: TyKind::Never.intern(Interner),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1024,6 +1026,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
pub(crate) enum Expectation {
|
pub(crate) enum Expectation {
|
||||||
None,
|
None,
|
||||||
HasType(Ty),
|
HasType(Ty),
|
||||||
|
#[allow(dead_code)]
|
||||||
Castable(Ty),
|
Castable(Ty),
|
||||||
RValueLikeUnsized(Ty),
|
RValueLikeUnsized(Ty),
|
||||||
}
|
}
|
||||||
@ -1102,6 +1105,10 @@ impl Expectation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
|
||||||
|
self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
|
||||||
|
}
|
||||||
|
|
||||||
/// Comment copied from rustc:
|
/// Comment copied from rustc:
|
||||||
/// Disregard "castable to" expectations because they
|
/// Disregard "castable to" expectations because they
|
||||||
/// can lead us astray. Consider for example `if cond
|
/// can lead us astray. Consider for example `if cond
|
||||||
|
@ -51,7 +51,7 @@ impl InferenceContext<'_> {
|
|||||||
.map(to_chalk_trait_id)
|
.map(to_chalk_trait_id)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let self_ty = TyKind::Error.intern(Interner);
|
let self_ty = self.result.standard_types.unknown.clone();
|
||||||
let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
|
let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
|
||||||
for bound in bounds.iter(Interner) {
|
for bound in bounds.iter(Interner) {
|
||||||
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
|
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
|
||||||
|
@ -87,16 +87,15 @@ impl<'a> InferenceContext<'a> {
|
|||||||
let expected = &expected.adjust_for_branches(&mut self.table);
|
let expected = &expected.adjust_for_branches(&mut self.table);
|
||||||
self.infer_expr(
|
self.infer_expr(
|
||||||
condition,
|
condition,
|
||||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||||
let mut both_arms_diverge = Diverges::Always;
|
let mut both_arms_diverge = Diverges::Always;
|
||||||
|
|
||||||
let result_ty = self.table.new_type_var();
|
|
||||||
let then_ty = self.infer_expr_inner(then_branch, expected);
|
let then_ty = self.infer_expr_inner(then_branch, expected);
|
||||||
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
|
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||||
let mut coerce = CoerceMany::new(result_ty);
|
let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
|
||||||
coerce.coerce(self, Some(then_branch), &then_ty);
|
coerce.coerce(self, Some(then_branch), &then_ty);
|
||||||
let else_ty = match else_branch {
|
let else_ty = match else_branch {
|
||||||
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
|
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
|
||||||
@ -113,7 +112,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
&Expr::Let { pat, expr } => {
|
&Expr::Let { pat, expr } => {
|
||||||
let input_ty = self.infer_expr(expr, &Expectation::none());
|
let input_ty = self.infer_expr(expr, &Expectation::none());
|
||||||
self.infer_pat(pat, &input_ty, BindingMode::default());
|
self.infer_pat(pat, &input_ty, BindingMode::default());
|
||||||
TyKind::Scalar(Scalar::Bool).intern(Interner)
|
self.result.standard_types.bool_.clone()
|
||||||
}
|
}
|
||||||
Expr::Block { statements, tail, label, id: _ } => {
|
Expr::Block { statements, tail, label, id: _ } => {
|
||||||
let old_resolver = mem::replace(
|
let old_resolver = mem::replace(
|
||||||
@ -188,10 +187,12 @@ impl<'a> InferenceContext<'a> {
|
|||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
}
|
}
|
||||||
&Expr::Loop { body, label } => {
|
&Expr::Loop { body, label } => {
|
||||||
|
// FIXME: should be:
|
||||||
|
// let ty = expected.coercion_target_type(&mut self.table);
|
||||||
let ty = self.table.new_type_var();
|
let ty = self.table.new_type_var();
|
||||||
let (breaks, ()) =
|
let (breaks, ()) =
|
||||||
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
|
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
|
||||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||||
});
|
});
|
||||||
|
|
||||||
match breaks {
|
match breaks {
|
||||||
@ -199,16 +200,16 @@ impl<'a> InferenceContext<'a> {
|
|||||||
self.diverges = Diverges::Maybe;
|
self.diverges = Diverges::Maybe;
|
||||||
breaks
|
breaks
|
||||||
}
|
}
|
||||||
None => TyKind::Never.intern(Interner),
|
None => self.result.standard_types.never.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Expr::While { condition, body, label } => {
|
&Expr::While { condition, body, label } => {
|
||||||
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
||||||
this.infer_expr(
|
this.infer_expr(
|
||||||
condition,
|
condition,
|
||||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
&Expectation::HasType(this.result.standard_types.bool_.clone()),
|
||||||
);
|
);
|
||||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// the body may not run, so it diverging doesn't mean we diverge
|
// the body may not run, so it diverging doesn't mean we diverge
|
||||||
@ -224,7 +225,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
|
|
||||||
self.infer_pat(pat, &pat_ty, BindingMode::default());
|
self.infer_pat(pat, &pat_ty, BindingMode::default());
|
||||||
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
|
||||||
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
|
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// the body may not run, so it diverging doesn't mean we diverge
|
// the body may not run, so it diverging doesn't mean we diverge
|
||||||
@ -382,12 +383,9 @@ impl<'a> InferenceContext<'a> {
|
|||||||
let expected = expected.adjust_for_branches(&mut self.table);
|
let expected = expected.adjust_for_branches(&mut self.table);
|
||||||
|
|
||||||
let result_ty = if arms.is_empty() {
|
let result_ty = if arms.is_empty() {
|
||||||
TyKind::Never.intern(Interner)
|
self.result.standard_types.never.clone()
|
||||||
} else {
|
} else {
|
||||||
match &expected {
|
expected.coercion_target_type(&mut self.table)
|
||||||
Expectation::HasType(ty) => ty.clone(),
|
|
||||||
_ => self.table.new_type_var(),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let mut coerce = CoerceMany::new(result_ty);
|
let mut coerce = CoerceMany::new(result_ty);
|
||||||
|
|
||||||
@ -400,7 +398,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
if let Some(guard_expr) = arm.guard {
|
if let Some(guard_expr) = arm.guard {
|
||||||
self.infer_expr(
|
self.infer_expr(
|
||||||
guard_expr,
|
guard_expr,
|
||||||
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
|
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +423,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
is_break: false,
|
is_break: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
TyKind::Never.intern(Interner)
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
Expr::Break { expr, label } => {
|
Expr::Break { expr, label } => {
|
||||||
let val_ty = if let Some(expr) = *expr {
|
let val_ty = if let Some(expr) = *expr {
|
||||||
@ -439,7 +437,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
// avoiding the borrowck
|
// avoiding the borrowck
|
||||||
let mut coerce = mem::replace(
|
let mut coerce = mem::replace(
|
||||||
&mut ctxt.coerce,
|
&mut ctxt.coerce,
|
||||||
CoerceMany::new(self.result.standard_types.unknown.clone()),
|
CoerceMany::new(expected.coercion_target_type(&mut self.table)),
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
|
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
|
||||||
@ -457,7 +455,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Never.intern(Interner)
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
Expr::Return { expr } => {
|
Expr::Return { expr } => {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
@ -466,7 +464,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
let unit = TyBuilder::unit();
|
let unit = TyBuilder::unit();
|
||||||
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
|
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
|
||||||
}
|
}
|
||||||
TyKind::Never.intern(Interner)
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
Expr::Yield { expr } => {
|
Expr::Yield { expr } => {
|
||||||
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
||||||
@ -479,14 +477,14 @@ impl<'a> InferenceContext<'a> {
|
|||||||
resume_ty
|
resume_ty
|
||||||
} else {
|
} else {
|
||||||
// FIXME: report error (yield expr in non-generator)
|
// FIXME: report error (yield expr in non-generator)
|
||||||
TyKind::Error.intern(Interner)
|
self.result.standard_types.unknown.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Yeet { expr } => {
|
Expr::Yeet { expr } => {
|
||||||
if let &Some(expr) = expr {
|
if let &Some(expr) = expr {
|
||||||
self.infer_expr_inner(expr, &Expectation::None);
|
self.infer_expr_inner(expr, &Expectation::None);
|
||||||
}
|
}
|
||||||
TyKind::Never.intern(Interner)
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
Expr::RecordLit { path, fields, spread, .. } => {
|
Expr::RecordLit { path, fields, spread, .. } => {
|
||||||
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
|
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
|
||||||
@ -611,8 +609,8 @@ impl<'a> InferenceContext<'a> {
|
|||||||
}
|
}
|
||||||
Expr::Cast { expr, type_ref } => {
|
Expr::Cast { expr, type_ref } => {
|
||||||
let cast_ty = self.make_ty(type_ref);
|
let cast_ty = self.make_ty(type_ref);
|
||||||
let _inner_ty =
|
// FIXME: propagate the "castable to" expectation
|
||||||
self.infer_expr_inner(*expr, &Expectation::Castable(cast_ty.clone()));
|
let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
|
||||||
// FIXME check the cast...
|
// FIXME check the cast...
|
||||||
cast_ty
|
cast_ty
|
||||||
}
|
}
|
||||||
@ -829,7 +827,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
|
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
|
||||||
self.infer_expr(
|
self.infer_expr(
|
||||||
repeat,
|
repeat,
|
||||||
&Expectation::has_type(
|
&Expectation::HasType(
|
||||||
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
|
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -852,7 +850,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
TyKind::Array(coerce.complete(), len).intern(Interner)
|
TyKind::Array(coerce.complete(), len).intern(Interner)
|
||||||
}
|
}
|
||||||
Expr::Literal(lit) => match lit {
|
Expr::Literal(lit) => match lit {
|
||||||
Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner),
|
Literal::Bool(..) => self.result.standard_types.bool_.clone(),
|
||||||
Literal::String(..) => {
|
Literal::String(..) => {
|
||||||
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
|
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
@ -1148,7 +1146,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
if let Some(expr) = else_branch {
|
if let Some(expr) = else_branch {
|
||||||
self.infer_expr_coerce(
|
self.infer_expr_coerce(
|
||||||
*expr,
|
*expr,
|
||||||
&Expectation::has_type(Ty::new(Interner, TyKind::Never)),
|
&Expectation::HasType(self.result.standard_types.never.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ impl<'a> InferenceContext<'a> {
|
|||||||
let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
|
let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
|
||||||
.fill(|x| {
|
.fill(|x| {
|
||||||
it.next().unwrap_or_else(|| match x {
|
it.next().unwrap_or_else(|| match x {
|
||||||
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
|
ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
|
||||||
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
|
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3200,6 +3200,8 @@ fn func() {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
#[test]
|
#[test]
|
||||||
fn castable_to() {
|
fn castable_to() {
|
||||||
check_infer(
|
check_infer(
|
||||||
@ -3224,10 +3226,60 @@ fn func() {
|
|||||||
120..122 '{}': ()
|
120..122 '{}': ()
|
||||||
138..184 '{ ...0]>; }': ()
|
138..184 '{ ...0]>; }': ()
|
||||||
148..149 'x': Box<[i32; 0]>
|
148..149 'x': Box<[i32; 0]>
|
||||||
152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]>
|
152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]>
|
||||||
152..164 'Box::new([])': Box<[i32; 0]>
|
152..164 'Box::new([])': Box<[{unknown}; 0]>
|
||||||
152..181 'Box::n...2; 0]>': Box<[i32; 0]>
|
152..181 'Box::n...2; 0]>': Box<[i32; 0]>
|
||||||
161..163 '[]': [i32; 0]
|
161..163 '[]': [{unknown}; 0]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn castable_to1() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
struct Ark<T>(T);
|
||||||
|
impl<T> Ark<T> {
|
||||||
|
fn foo(&self) -> *const T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn f<T>(t: Ark<T>) {
|
||||||
|
Ark::foo(&t) as *const ();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
47..51 'self': &Ark<T>
|
||||||
|
65..88 '{ ... }': *const T
|
||||||
|
75..82 '&self.0': &T
|
||||||
|
76..80 'self': &Ark<T>
|
||||||
|
76..82 'self.0': T
|
||||||
|
99..100 't': Ark<T>
|
||||||
|
110..144 '{ ... (); }': ()
|
||||||
|
116..124 'Ark::foo': fn foo<T>(&Ark<T>) -> *const T
|
||||||
|
116..128 'Ark::foo(&t)': *const T
|
||||||
|
116..141 'Ark::f...nst ()': *const ()
|
||||||
|
125..127 '&t': &Ark<T>
|
||||||
|
126..127 't': Ark<T>
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
#[test]
|
||||||
|
fn castable_to2() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
fn func() {
|
||||||
|
let x = &0u32 as *const _;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
10..44 '{ ...t _; }': ()
|
||||||
|
20..21 'x': *const {unknown}
|
||||||
|
24..29 '&0u32': &u32
|
||||||
|
24..41 '&0u32 ...onst _': *const {unknown}
|
||||||
|
25..29 '0u32': u32
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user