Normalize type alias in projected_ty

This commit is contained in:
hkalbasi 2023-07-17 01:16:26 +03:30
parent 41b8b0b77d
commit 832eb0d94c
2 changed files with 45 additions and 4 deletions

View File

@ -3,9 +3,14 @@
use std::{fmt::Display, iter}; use std::{fmt::Display, iter};
use crate::{ use crate::{
consteval::usize_const, db::HirDatabase, display::HirDisplay, infer::PointerCast, consteval::usize_const,
lang_items::is_box, mapping::ToChalk, CallableDefId, ClosureId, Const, ConstScalar, db::HirDatabase,
InferenceResult, Interner, MemoryMap, Substitution, Ty, TyKind, 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 base_db::CrateId;
use chalk_ir::Mutability; use chalk_ir::Mutability;
@ -34,6 +39,7 @@
}; };
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use stdx::{impl_from, never}; use stdx::{impl_from, never};
use triomphe::Arc;
use super::consteval::{intern_const_scalar, try_const_usize}; use super::consteval::{intern_const_scalar, try_const_usize};
@ -131,11 +137,19 @@ pub enum ProjectionElem<V, T> {
impl<V, T> ProjectionElem<V, T> { impl<V, T> ProjectionElem<V, T> {
pub fn projected_ty( pub fn projected_ty(
&self, &self,
base: Ty, mut base: Ty,
db: &dyn HirDatabase, db: &dyn HirDatabase,
closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
krate: CrateId, krate: CrateId,
) -> Ty { ) -> 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 { match self {
ProjectionElem::Deref => match &base.data(Interner).kind { ProjectionElem::Deref => match &base.data(Interner).kind {
TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(), TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),

View File

@ -1084,6 +1084,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] #[test]
fn allow_unused_mut_for_identifiers_starting_with_underline() { fn allow_unused_mut_for_identifiers_starting_with_underline() {
check_diagnostics( check_diagnostics(