Repository: rust-lang/rust-analyzer (rust)

Issue:
Panic when analyzing impl Trait used in projection
<!--
Troubleshooting guide: https://rust-analyzer.github.io/manual.html#troubleshooting
Forum for questions: https://users.rust-lang.org/c/ide/14

Before submitting, please make sure that you're not running into one of these known issues:

 1. extension doesn't load in VSCodium: #11080
 2. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107

Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
-->

With a program like the one below, rust-analyzer panics via chalk with a message about a bad De Bruijn index. 
I can't contrive a way to reproduce this with the chalk CLI, so I'm guessing it's an issue with how the RA hir code drives type canonicalization.

```rust
use std::{future::Future, marker::PhantomData};

struct MyFuture<T, F>(PhantomData<(T, F)>);

type MyFutureFrom<F> = MyFuture<<F as Future>::Output, F>;

fn x<X>() -> MyFutureFrom<impl Future<Output = ()>> {
    MyFuture::<(), std::future::Ready<()>>(PhantomData)
}
```

Error:

```
thread 'Worker' panicked at 'unexpected free variable with depth `^0.0` with outer binder ^0', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/chalk-ir-0.84.0/src/fold.rs:143:13
```

<details>
<summary>Backtrace</summary>

```
stack backtrace:
   0: _rust_begin_unwind
   1: core::panicking::panic_fmt
   2: chalk_ir::fold::TypeFolder::fold_free_var_ty
   3: <chalk_ir::Ty<I> as chalk_ir::fold::TypeSuperFoldable<I>>::super_fold_with
   4: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::GenericArg<I>>::fold_with
   5: <smallvec::SmallVec<A> as core::iter::traits::collect::Extend<<A as smallvec::Array>::Item>>::extend
   6: <hir_ty::interner::Interner as chalk_ir::interner::Interner>::intern_substitution
   7: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::Substitution<I>>::fold_with
   8: <chalk_ir::Ty<I> as chalk_ir::fold::TypeSuperFoldable<I>>::super_fold_with
   9: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::GenericArg<I>>::fold_with
  10: <smallvec::SmallVec<A> as core::iter::traits::collect::Extend<<A as smallvec::Array>::Item>>::extend
  11: <hir_ty::interner::Interner as chalk_ir::interner::Interner>::intern_substitution
  12: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::Substitution<I>>::fold_with
  13: chalk_ir::_::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::WhereClause<I>>::fold_with
  14: chalk_ir::_::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::DomainGoal<I>>::fold_with
  15: <chalk_ir::Goal<I> as chalk_ir::fold::TypeSuperFoldable<I>>::super_fold_with
  16: chalk_ir::_::<impl chalk_ir::fold::TypeFoldable<_I> for chalk_ir::InEnvironment<G>>::fold_with
  17: chalk_solve::infer::canonicalize::<impl chalk_solve::infer::InferenceTable<I>>::canonicalize
  18: hir_ty::infer::unify::InferenceTable::canonicalize
  19: hir_ty::infer::unify::InferenceTable::register_obligation_in_env
  20: hir_ty::infer::unify::InferenceTable::normalize_projection_ty
  21: <hir_ty::fold_tys_and_consts::TyFolder<F> as chalk_ir::fold::TypeFolder<hir_ty::interner::Interner>>::fold_ty
  22: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::GenericArg<I>>::fold_with
  23: <smallvec::SmallVec<A> as core::iter::traits::collect::Extend<<A as smallvec::Array>::Item>>::extend
  24: <hir_ty::interner::Interner as chalk_ir::interner::Interner>::intern_substitution
  25: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::Substitution<I>>::fold_with
  26: <chalk_ir::Ty<I> as chalk_ir::fold::TypeSuperFoldable<I>>::super_fold_with
  27: <hir_ty::fold_tys_and_consts::TyFolder<F> as chalk_ir::fold::TypeFolder<hir_ty::interner::Interner>>::fold_ty
  28: hir_ty::infer::InferenceContext::make_ty_with_mode
  29: hir_ty::infer::infer_query
  30: salsa::runtime::Runtime::execute_query_implementation
  31: salsa::derived::slot::Slot<Q,MP>::read_upgrade
  32: salsa::derived::slot::Slot<Q,MP>::read
  33: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::try_fetch
  34: <DB as hir_ty::db::HirDatabase>::infer_query::__shim
  35: <DB as hir_ty::db::HirDatabase>::infer_query
  36: hir_ty::db::infer_wait
  37: <DB as hir_ty::db::HirDatabase>::infer
  38: hir::DefWithBody::diagnostics
  39: hir::ModuleDef::diagnostics
  40: hir::Module::diagnostics
  41: ide_diagnostics::diagnostics
  42: std::panicking::try
  43: ide::Analysis::assists_with_fixes
  44: rust_analyzer::handlers::handle_code_action
  45: std::panicking::try
  46: <F as threadpool::FnBox>::call_box
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```

</details>

I think the critical elements are:

* A function returns an impl trait value whose type is used in a projection type (within the type alias)
* That function takes a type parameter which is captured in the impl trait desugaring (I believe this is the free variable in the error message)

**rust-analyzer version**: 0.3.1221-standalone (73ab709b3 2022-09-24) [but I believe this has been happening for at least a few months]

**rustc version**: rustc 1.64.0 (a55dd71d5 2022-09-19)

**relevant settings**: N/A


Pull request:
fix: normalize projection after discarding free `BoundVar`s in RPIT
Fixes #13307

When we lower the return type of a function, it may contain free `BoundVar`s in `OpaqueType`'s substitution, which would cause panic during canonicalization as part of projection normalization. Those `BoundVar`s are irrelevant in this context and will be discarded, and we should defer projection normalization until then.

Patch:
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 874a54fc3e..ad7ec485e9 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -503,7 +503,7 @@ impl<'a> InferenceContext<'a> {
             result: InferenceResult::default(),
             table: unify::InferenceTable::new(db, trait_env.clone()),
             trait_env,
-            return_ty: TyKind::Error.intern(Interner), // set in collect_fn_signature
+            return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
             resume_yield_tys: None,
             db,
             owner,
@@ -582,14 +582,17 @@ impl<'a> InferenceContext<'a> {
         } else {
             &*data.ret_type
         };
-        let return_ty = self.make_ty_with_mode(return_ty, ImplTraitLoweringMode::Opaque);
-        self.return_ty = return_ty;
 
-        if let Some(rpits) = self.db.return_type_impl_traits(func) {
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
+            .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+        let return_ty = ctx.lower_ty(return_ty);
+        let return_ty = self.insert_type_vars(return_ty);
+
+        let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
             // RPIT opaque types use substitution of their parent function.
             let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
-            self.return_ty = fold_tys(
-                self.return_ty.clone(),
+            fold_tys(
+                return_ty,
                 |ty, _| {
                     let opaque_ty_id = match ty.kind(Interner) {
                         TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
@@ -610,14 +613,18 @@ impl<'a> InferenceContext<'a> {
                         let (var_predicate, binders) = predicate
                             .substitute(Interner, &var_subst)
                             .into_value_and_skipped_binders();
-                        always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
+                        always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
                         self.push_obligation(var_predicate.cast(Interner));
                     }
                     var
                 },
                 DebruijnIndex::INNERMOST,
-            );
-        }
+            )
+        } else {
+            return_ty
+        };
+
+        self.return_ty = self.normalize_associated_types_in(return_ty);
     }
 
     fn infer_body(&mut self) {
@@ -652,23 +659,14 @@ impl<'a> InferenceContext<'a> {
         self.result.diagnostics.push(diagnostic);
     }
 
-    fn make_ty_with_mode(
-        &mut self,
-        type_ref: &TypeRef,
-        impl_trait_mode: ImplTraitLoweringMode,
-    ) -> Ty {
+    fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
         // FIXME use right resolver for block
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
-            .with_impl_trait_mode(impl_trait_mode);
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
         let ty = ctx.lower_ty(type_ref);
         let ty = self.insert_type_vars(ty);
         self.normalize_associated_types_in(ty)
     }
 
-    fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
-        self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed)
-    }
-
     fn err_ty(&self) -> Ty {
         self.result.standard_types.unknown.clone()
     }
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index f4f3c723ab..3c6489fa97 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -3,13 +3,8 @@
 use std::sync::Arc;
 
 use chalk_ir::{AdtId, TyKind};
-use hir_def::{
-    layout::{
-        Abi, FieldsShape, Integer, Layout, LayoutCalculator, LayoutError, Primitive, ReprOptions,
-        RustcEnumVariantIdx, Scalar, Size, StructKind, TargetDataLayout, Variants, WrappingRange,
-    },
-    LocalFieldId,
-};
+pub(self) use hir_def::layout::*;
+use hir_def::LocalFieldId;
 use stdx::never;
 
 use crate::{db::HirDatabase, Interner, Substitution, Ty};
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index e938295535..d9791a4b63 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -8,7 +8,7 @@ use hir_def::{
     AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
 };
 use la_arena::RawIdx;
-use smallvec::SmallVec;
+use rustc_index::vec::IndexVec;
 
 use crate::{db::HirDatabase, lang_items::is_unsafe_cell, layout::field_ty, Substitution};
 
@@ -34,13 +34,13 @@ pub fn layout_of_adt_query(
     let (variants, is_enum, is_union, repr) = match def {
         AdtId::StructId(s) => {
             let data = db.struct_data(s);
-            let mut r = SmallVec::<[_; 1]>::new();
+            let mut r = IndexVec::new();
             r.push(handle_variant(s.into(), &data.variant_data)?);
             (r, false, false, data.repr.unwrap_or_default())
         }
         AdtId::UnionId(id) => {
             let data = db.union_data(id);
-            let mut r = SmallVec::new();
+            let mut r = IndexVec::new();
             r.push(handle_variant(id.into(), &data.variant_data)?);
             (r, false, true, data.repr.unwrap_or_default())
         }
@@ -55,12 +55,11 @@ pub fn layout_of_adt_query(
                         &v.variant_data,
                     )
                 })
-                .collect::<Result<SmallVec<_>, _>>()?;
+                .collect::<Result<IndexVec<RustcEnumVariantIdx, _>, _>>()?;
             (r, true, false, data.repr.unwrap_or_default())
         }
     };
-    let variants =
-        variants.iter().map(|x| x.iter().collect::<Vec<_>>()).collect::<SmallVec<[_; 1]>>();
+    let variants = variants.iter().map(|x| x.iter().collect::<Vec<_>>()).collect::<Vec<_>>();
     let variants = variants.iter().map(|x| x.iter().collect()).collect();
     if is_union {
         cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)
diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs
index b248031f15..b76274bb85 100644
--- a/crates/hir-ty/src/layout/target.rs
+++ b/crates/hir-ty/src/layout/target.rs
@@ -6,7 +6,7 @@ use hir_def::layout::TargetDataLayout;
 
 use crate::db::HirDatabase;
 
-use hir_def::layout::{AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size};
+use super::{AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size};
 
 pub fn current_target_data_layout_query(db: &dyn HirDatabase) -> Arc<TargetDataLayout> {
     let crate_graph = db.crate_graph();
diff --git a/crates/ide-assists/src/handlers/remove_parentheses.rs b/crates/ide-assists/src/handlers/remove_parentheses.rs
deleted file mode 100644
index 185beda9d0..0000000000
--- a/crates/ide-assists/src/handlers/remove_parentheses.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use syntax::{ast, AstNode};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: remove_parentheses
-//
-// Removes redundant parentheses.
-//
-// ```
-// fn main() {
-//     _ = $0(2) + 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//     _ = 2 + 2;
-// }
-// ```
-pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let parens = ctx.find_node_at_offset::<ast::ParenExpr>()?;
-
-    let cursor_in_range =
-        parens.l_paren_token()?.text_range().contains_range(ctx.selection_trimmed())
-            || parens.r_paren_token()?.text_range().contains_range(ctx.selection_trimmed());
-    if !cursor_in_range {
-        return None;
-    }
-
-    let expr = parens.expr()?;
-
-    let parent = ast::Expr::cast(parens.syntax().parent()?);
-    let is_ok_to_remove = expr.precedence() >= parent.as_ref().and_then(ast::Expr::precedence);
-    if !is_ok_to_remove {
-        return None;
-    }
-
-    let target = parens.syntax().text_range();
-    acc.add(
-        AssistId("remove_parentheses", AssistKind::Refactor),
-        "Remove redundant parentheses",
-        target,
-        |builder| builder.replace_ast(parens.into(), expr),
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn remove_parens_simple() {
-        check_assist(remove_parentheses, r#"fn f() { $0(2) + 2; }"#, r#"fn f() { 2 + 2; }"#);
-        check_assist(remove_parentheses, r#"fn f() { ($02) + 2; }"#, r#"fn f() { 2 + 2; }"#);
-        check_assist(remove_parentheses, r#"fn f() { (2)$0 + 2; }"#, r#"fn f() { 2 + 2; }"#);
-        check_assist(remove_parentheses, r#"fn f() { (2$0) + 2; }"#, r#"fn f() { 2 + 2; }"#);
-    }
-
-    #[test]
-    fn remove_parens_precedence() {
-        check_assist(
-            remove_parentheses,
-            r#"fn f() { $0(2 * 3) + 1; }"#,
-            r#"fn f() { 2 * 3 + 1; }"#,
-        );
-        check_assist(remove_parentheses, r#"fn f() { ( $0(2) ); }"#, r#"fn f() { ( 2 ); }"#);
-        check_assist(remove_parentheses, r#"fn f() { $0(2?)?; }"#, r#"fn f() { 2??; }"#);
-        check_assist(remove_parentheses, r#"fn f() { f(($02 + 2)); }"#, r#"fn f() { f(2 + 2); }"#);
-        check_assist(
-            remove_parentheses,
-            r#"fn f() { (1<2)&&$0(3>4); }"#,
-            r#"fn f() { (1<2)&&3>4; }"#,
-        );
-    }
-
-    #[test]
-    fn remove_parens_doesnt_apply_precedence() {
-        check_assist_not_applicable(remove_parentheses, r#"fn f() { $0(2 + 2) * 8; }"#);
-        check_assist_not_applicable(remove_parentheses, r#"fn f() { $0(2 + 2).f(); }"#);
-        check_assist_not_applicable(remove_parentheses, r#"fn f() { $0(2 + 2).await; }"#);
-        check_assist_not_applicable(remove_parentheses, r#"fn f() { $0!(2..2); }"#);
-    }
-
-    #[test]
-    fn remove_parens_doesnt_apply_with_cursor_not_on_paren() {
-        check_assist_not_applicable(remove_parentheses, r#"fn f() { (2 +$0 2) }"#);
-        check_assist_not_applicable(remove_parentheses, r#"fn f() {$0 (2 + 2) }"#);
-    }
-}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 8b1247c640..a55de800b3 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -179,7 +179,6 @@ mod handlers {
     mod remove_dbg;
     mod remove_mut;
     mod remove_unused_param;
-    mod remove_parentheses;
     mod reorder_fields;
     mod reorder_impl_items;
     mod replace_try_expr_with_match;
@@ -281,7 +280,6 @@ mod handlers {
             remove_dbg::remove_dbg,
             remove_mut::remove_mut,
             remove_unused_param::remove_unused_param,
-            remove_parentheses::remove_parentheses,
             reorder_fields::reorder_fields,
             reorder_impl_items::reorder_impl_items,
             replace_try_expr_with_match::replace_try_expr_with_match,
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index ef434e51c1..f37c9f4a6d 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -395,17 +395,17 @@ pub(super) fn definition(
             let id = it.index();
             let layout = it.layout(db).ok()?;
             let offset = match var_def {
-                hir::VariantDef::Struct(s) => Adt::from(s)
-                    .layout(db)
-                    .ok()
-                    .map(|layout| format!(", offset = {}", layout.fields.offset(id).bytes())),
-                _ => None,
+                hir::VariantDef::Struct(s) => {
+                    let layout = Adt::from(s).layout(db).ok()?;
+                    layout.fields.offset(id)
+                }
+                _ => return None,
             };
             Some(format!(
-                "size = {}, align = {}{}",
+                "size = {}, align = {}, offset = {}",
                 layout.size.bytes(),
                 layout.align.abi.bytes(),
-                offset.as_deref().unwrap_or_default()
+                offset.bytes()
             ))
         }),
         Definition::Module(it) => label_and_docs(db, it),
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index 10c0457583..4aa64d0d6e 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -9,7 +9,6 @@ mod operators;
 pub mod edit;
 pub mod edit_in_place;
 pub mod make;
-pub mod prec;
 
 use std::marker::PhantomData;
 
diff --git a/crates/syntax/src/ast/prec.rs b/crates/syntax/src/ast/prec.rs
deleted file mode 100644
index 6253c4dc3e..0000000000
--- a/crates/syntax/src/ast/prec.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-//! Precedence representation.
-
-use crate::ast::{self, BinExpr, Expr};
-
-/// Precedence of an expression.
-#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
-pub enum ExprPrecedence {
-    // N.B.: Order is important
-    Closure,
-    Jump,
-    Range,
-    Bin(BinOpPresedence),
-    Prefix,
-    Postfix,
-    Paren,
-}
-
-/// Precedence of a binary operator.
-#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
-pub enum BinOpPresedence {
-    // N.B.: Order is important
-    /// `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `|=`, `&=`
-    Assign,
-    /// `||`
-    LOr,
-    /// `&&`
-    LAnd,
-    /// `<`, `<=`, `>`, `>=`, `==` and `!=`
-    Cmp,
-    /// `|`
-    BitOr,
-    /// `^`
-    BitXor,
-    /// `&`
-    BitAnd,
-    /// `<<` and `>>`
-    Shift,
-    /// `+` and `-`
-    Add,
-    /// `*`, `/` and `%`
-    Mul,
-    /// `as`
-    As,
-}
-
-impl Expr {
-    /// Returns precedence of this expression.
-    /// Usefull to preserve semantics in assists.
-    ///
-    /// Returns `None` if this is a [`BinExpr`] and its [`op_kind`] returns `None`.
-    ///
-    /// [`op_kind`]: BinExpr::op_kind
-    /// [`BinExpr`]: Expr::BinExpr
-    pub fn precedence(&self) -> Option<ExprPrecedence> {
-        // Copied from <https://github.com/rust-lang/rust/blob/b6852428a8ea9728369b64b9964cad8e258403d3/compiler/rustc_ast/src/util/parser.rs#L296>
-        use Expr::*;
-
-        let prec = match self {
-            ClosureExpr(_) => ExprPrecedence::Closure,
-
-            ContinueExpr(_) | ReturnExpr(_) | YieldExpr(_) | BreakExpr(_) => ExprPrecedence::Jump,
-
-            RangeExpr(_) => ExprPrecedence::Range,
-
-            BinExpr(bin_expr) => return bin_expr.precedence().map(ExprPrecedence::Bin),
-            CastExpr(_) => ExprPrecedence::Bin(BinOpPresedence::As),
-
-            BoxExpr(_) | RefExpr(_) | LetExpr(_) | PrefixExpr(_) => ExprPrecedence::Prefix,
-
-            AwaitExpr(_) | CallExpr(_) | MethodCallExpr(_) | FieldExpr(_) | IndexExpr(_)
-            | TryExpr(_) | MacroExpr(_) => ExprPrecedence::Postfix,
-
-            ArrayExpr(_) | TupleExpr(_) | Literal(_) | PathExpr(_) | ParenExpr(_) | IfExpr(_)
-            | WhileExpr(_) | ForExpr(_) | LoopExpr(_) | MatchExpr(_) | BlockExpr(_)
-            | RecordExpr(_) | UnderscoreExpr(_) => ExprPrecedence::Paren,
-        };
-
-        Some(prec)
-    }
-}
-
-impl BinExpr {
-    /// Returns precedence of this binary expression.
-    /// Usefull to preserve semantics in assists.
-    ///
-    /// Returns `None` if [`op_kind`] returns `None`.
-    ///
-    /// [`op_kind`]: BinExpr::op_kind
-    pub fn precedence(&self) -> Option<BinOpPresedence> {
-        use ast::{ArithOp::*, BinaryOp::*, LogicOp::*};
-
-        let prec = match self.op_kind()? {
-            LogicOp(op) => match op {
-                And => BinOpPresedence::LAnd,
-                Or => BinOpPresedence::LOr,
-            },
-            ArithOp(op) => match op {
-                Add => BinOpPresedence::Add,
-                Mul => BinOpPresedence::Mul,
-                Sub => BinOpPresedence::Add,
-                Div => BinOpPresedence::Mul,
-                Rem => BinOpPresedence::Mul,
-                Shl => BinOpPresedence::Shift,
-                Shr => BinOpPresedence::Shift,
-                BitXor => BinOpPresedence::BitXor,
-                BitOr => BinOpPresedence::BitOr,
-                BitAnd => BinOpPresedence::BitAnd,
-            },
-            CmpOp(_) => BinOpPresedence::Cmp,
-            Assignment { .. } => BinOpPresedence::Assign,
-        };
-
-        Some(prec)
-    }
-}
diff --git a/editors/code/package.json b/editors/code/package.json
index 5b83701a68..ad5f97bb19 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1788,12 +1788,6 @@
                     "group": "navigation@1000"
                 }
             ]
-        },
-        "jsonValidation": [
-            {
-                "fileMatch": "rust-project.json",
-                "url": "https://json.schemastore.org/rust-project.json"
-            }
-        ]
+        }
     }
 }


Test patch:
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 3d7194b6f4..a9fd01ee01 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1388,6 +1388,22 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
     );
 }
 
+#[test]
+fn return_pos_impl_trait_in_projection() {
+    // Note that the unused type param `X` is significant; see #13307.
+    check_no_mismatches(
+        r#"
+//- minicore: sized
+trait Future { type Output; }
+impl Future for () { type Output = i32; }
+type Foo<F> = (<F as Future>::Output, F);
+fn foo<X>() -> Foo<impl Future<Output = ()>> {
+    (0, ())
+}
+"#,
+    )
+}
+
 #[test]
 fn dyn_trait() {
     check_infer(
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 80b8c27c7c..ccd38119c4 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -1978,23 +1978,6 @@ impl Walrus {
     )
 }
 
-#[test]
-fn doctest_remove_parentheses() {
-    check_doc_test(
-        "remove_parentheses",
-        r#####"
-fn main() {
-    _ = $0(2) + 2;
-}
-"#####,
-        r#####"
-fn main() {
-    _ = 2 + 2;
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_remove_unused_param() {
     check_doc_test(
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 34dd7fb621..f82fd6d028 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -5176,28 +5176,6 @@ enum Enum {
     );
 }
 
-#[test]
-fn hover_record_variant_field() {
-    check(
-        r#"
-enum Enum {
-    RecordV { field$0: u32 }
-}
-"#,
-        expect![[r#"
-            *field*
-
-            ```rust
-            test::RecordV
-            ```
-
-            ```rust
-            field: u32 // size = 4, align = 4
-            ```
-        "#]],
-    );
-}
-
 #[test]
 fn hover_trait_impl_assoc_item_def_doc_forwarding() {
     check(