about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-07-17 01:16:26 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-07-17 01:16:26 +0330
commit832eb0d94c54e9d983e4f2df2ce9b78e6edd30f6 (patch)
tree30712fff458713d681f7ff90209d2021f2eb534b
parent41b8b0b77d5f30ff63aa3c2fdf87e643ca9481e5 (diff)
downloadrust-832eb0d94c54e9d983e4f2df2ce9b78e6edd30f6.tar.gz
rust-832eb0d94c54e9d983e4f2df2ce9b78e6edd30f6.zip
Normalize type alias in projected_ty
-rw-r--r--crates/hir-ty/src/mir.rs22
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs27
2 files changed, 45 insertions, 4 deletions
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index dc846fc3947..da5b496e141 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -3,9 +3,14 @@
 use std::{fmt::Display, iter};
 
 use crate::{
-    consteval::usize_const, db::HirDatabase, display::HirDisplay, infer::PointerCast,
-    lang_items::is_box, mapping::ToChalk, CallableDefId, ClosureId, Const, ConstScalar,
-    InferenceResult, Interner, MemoryMap, Substitution, Ty, TyKind,
+    consteval::usize_const,
+    db::HirDatabase,
+    display::HirDisplay,
+    infer::{normalize, PointerCast},
+    lang_items::is_box,
+    mapping::ToChalk,
+    CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap,
+    Substitution, TraitEnvironment, Ty, TyKind,
 };
 use base_db::CrateId;
 use chalk_ir::Mutability;
@@ -34,6 +39,7 @@ pub use monomorphization::{
 };
 use smallvec::{smallvec, SmallVec};
 use stdx::{impl_from, never};
+use triomphe::Arc;
 
 use super::consteval::{intern_const_scalar, try_const_usize};
 
@@ -131,11 +137,19 @@ pub enum ProjectionElem<V, T> {
 impl<V, T> ProjectionElem<V, T> {
     pub fn projected_ty(
         &self,
-        base: Ty,
+        mut base: Ty,
         db: &dyn HirDatabase,
         closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
         krate: CrateId,
     ) -> Ty {
+        if matches!(base.data(Interner).kind, TyKind::Alias(_) | TyKind::AssociatedType(..)) {
+            base = normalize(
+                db,
+                // FIXME: we should get this from caller
+                Arc::new(TraitEnvironment::empty(krate)),
+                base,
+            );
+        }
         match self {
             ProjectionElem::Deref => match &base.data(Interner).kind {
                 TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 935f12a3969..e0c3bedce46 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -1085,6 +1085,33 @@ fn f() {
     }
 
     #[test]
+    fn regression_15143() {
+        check_diagnostics(
+            r#"
+        trait Tr {
+            type Ty;
+        }
+
+        struct A;
+
+        impl Tr for A {
+            type Ty = (u32, i64);
+        }
+
+        struct B<T: Tr> {
+            f: <T as Tr>::Ty,
+        }
+
+        fn main(b: B<A>) {
+            let f = b.f.0;
+            f = 5;
+          //^^^^^ 💡 error: cannot mutate immutable variable `f`
+        }
+            "#,
+        );
+    }
+
+    #[test]
     fn allow_unused_mut_for_identifiers_starting_with_underline() {
         check_diagnostics(
             r#"