mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Merge #8938
8938: internal: Fix #8931 r=flodiebold a=flodiebold - and add some better checking for similar bugs Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
commit
0ec4ce1e9b
@ -2053,7 +2053,7 @@ impl Type {
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let canonical = hir_ty::replace_errors_with_variables(self.ty.clone());
|
||||
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
||||
|
||||
let env = self.env.clone();
|
||||
let krate = krate.id;
|
||||
@ -2222,7 +2222,7 @@ impl Type {
|
||||
}
|
||||
|
||||
pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
|
||||
let tys = hir_ty::replace_errors_with_variables((self.ty.clone(), other.ty.clone()));
|
||||
let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
|
||||
could_unify(db, self.env.clone(), &tys)
|
||||
}
|
||||
}
|
||||
|
@ -505,9 +505,10 @@ impl<'db> SemanticsImpl<'db> {
|
||||
}
|
||||
|
||||
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
|
||||
// FIXME: this erases Substs
|
||||
// FIXME: this erases Substs, we should instead record the correct
|
||||
// substitution during inference and use that
|
||||
let func = self.resolve_method_call(call)?;
|
||||
let (ty, _) = self.db.value_ty(func.into()).into_value_and_skipped_binders();
|
||||
let ty = hir_ty::TyBuilder::value_ty(self.db, func.into()).fill_with_unknown().build();
|
||||
let resolver = self.analyze(call.syntax()).resolver;
|
||||
let ty = Type::new_with_resolver(self.db, &resolver, ty)?;
|
||||
let mut res = ty.as_callable(self.db)?;
|
||||
|
@ -43,7 +43,6 @@ use hir_def::{
|
||||
type_ref::{ConstScalar, Rawness},
|
||||
TypeParamId,
|
||||
};
|
||||
use stdx::always;
|
||||
|
||||
use crate::{db::HirDatabase, utils::generics};
|
||||
|
||||
@ -329,14 +328,17 @@ pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
|
||||
t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
|
||||
}
|
||||
|
||||
pub fn replace_errors_with_variables<T>(t: T) -> Canonical<T::Result>
|
||||
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
|
||||
/// ensures there are no unbound variables or inference variables anywhere in
|
||||
/// the `t`.
|
||||
pub fn replace_errors_with_variables<T>(t: &T) -> Canonical<T::Result>
|
||||
where
|
||||
T: HasInterner<Interner = Interner> + Fold<Interner>,
|
||||
T: HasInterner<Interner = Interner> + Fold<Interner> + Clone,
|
||||
T::Result: HasInterner<Interner = Interner>,
|
||||
{
|
||||
use chalk_ir::{
|
||||
fold::{Folder, SuperFold},
|
||||
Fallible,
|
||||
Fallible, NoSolution,
|
||||
};
|
||||
struct ErrorReplacer {
|
||||
vars: usize,
|
||||
@ -363,18 +365,88 @@ where
|
||||
|
||||
fn fold_inference_ty(
|
||||
&mut self,
|
||||
var: InferenceVar,
|
||||
kind: TyVariableKind,
|
||||
_var: InferenceVar,
|
||||
_kind: TyVariableKind,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Ty> {
|
||||
always!(false);
|
||||
Ok(TyKind::InferenceVar(var, kind).intern(&Interner))
|
||||
if cfg!(debug_assertions) {
|
||||
// we don't want to just panic here, because then the error message
|
||||
// won't contain the whole thing, which would not be very helpful
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(TyKind::Error.intern(&Interner))
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_free_var_ty(
|
||||
&mut self,
|
||||
_bound_var: BoundVar,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Ty> {
|
||||
if cfg!(debug_assertions) {
|
||||
// we don't want to just panic here, because then the error message
|
||||
// won't contain the whole thing, which would not be very helpful
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(TyKind::Error.intern(&Interner))
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_inference_const(
|
||||
&mut self,
|
||||
_ty: Ty,
|
||||
_var: InferenceVar,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Const> {
|
||||
if cfg!(debug_assertions) {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(dummy_usize_const())
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_free_var_const(
|
||||
&mut self,
|
||||
_ty: Ty,
|
||||
_bound_var: BoundVar,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Const> {
|
||||
if cfg!(debug_assertions) {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(dummy_usize_const())
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_inference_lifetime(
|
||||
&mut self,
|
||||
_var: InferenceVar,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Lifetime> {
|
||||
if cfg!(debug_assertions) {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(static_lifetime())
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_free_var_lifetime(
|
||||
&mut self,
|
||||
_bound_var: BoundVar,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Fallible<Lifetime> {
|
||||
if cfg!(debug_assertions) {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(static_lifetime())
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut error_replacer = ErrorReplacer { vars: 0 };
|
||||
let value = t
|
||||
.fold_with(&mut error_replacer, DebruijnIndex::INNERMOST)
|
||||
.expect("fold failed unexpectedly");
|
||||
let value = match t.clone().fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) {
|
||||
Ok(t) => t,
|
||||
Err(_) => panic!("Encountered unbound or inference vars in {:?}", t),
|
||||
};
|
||||
let kinds = (0..error_replacer.vars).map(|_| {
|
||||
chalk_ir::CanonicalVarKind::new(
|
||||
chalk_ir::VariableKind::Ty(TyVariableKind::General),
|
||||
|
@ -454,4 +454,34 @@ mod foo {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_8931() {
|
||||
check(
|
||||
r#"
|
||||
#[lang = "fn_once"]
|
||||
trait FnOnce<Args> {
|
||||
type Output;
|
||||
}
|
||||
struct S;
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn foo(&self) -> &[u8] { loop {} }
|
||||
}
|
||||
|
||||
impl S {
|
||||
fn indented(&mut self, f: impl FnOnce(&mut Self)) {
|
||||
}
|
||||
|
||||
fn f(&mut self, v: Foo) {
|
||||
self.indented(|this| v.$0)
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me foo() fn(&self) -> &[u8]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user