Skip to content

Commit 9370cb5

Browse files
Refactor handling of generic params in hir::Type
The essence of the new handling is that `hir::Type` now remembers its owner (and not `ParamEnv`; we could remember both but that is unnecessary) and refuse (panics) to work with types not from the same owner. It would be best if we could enforce this statically, but unfortunately we can't.
1 parent ad61c8d commit 9370cb5

37 files changed

Lines changed: 896 additions & 967 deletions

crates/hir-ty/src/traits.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub fn implements_trait_unique<'db>(
121121
env: ParamEnvAndCrate<'db>,
122122
trait_: TraitId,
123123
) -> bool {
124-
implements_trait_unique_impl(db, env, trait_, &mut |infcx| {
124+
implements_trait_unique_with_infcx(db, env, trait_, &mut |infcx| {
125125
infcx.fill_rest_fresh_args(Span::Dummy, trait_.into(), [ty.into()])
126126
})
127127
}
@@ -133,10 +133,10 @@ pub fn implements_trait_unique_with_args<'db>(
133133
trait_: TraitId,
134134
args: GenericArgs<'db>,
135135
) -> bool {
136-
implements_trait_unique_impl(db, env, trait_, &mut |_| args)
136+
implements_trait_unique_with_infcx(db, env, trait_, &mut |_| args)
137137
}
138138

139-
fn implements_trait_unique_impl<'db>(
139+
pub fn implements_trait_unique_with_infcx<'db>(
140140
db: &'db dyn HirDatabase,
141141
env: ParamEnvAndCrate<'db>,
142142
trait_: TraitId,

crates/hir/src/attrs.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use stdx::never;
2626

2727
use crate::{
2828
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, EnumVariant,
29-
ExternCrateDecl, Field, Function, GenericParam, HasCrate, Impl, LangItem, LifetimeParam, Macro,
30-
Module, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant,
29+
ExternCrateDecl, Field, Function, GenericParam, Impl, LangItem, LifetimeParam, Macro, Module,
30+
ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant,
3131
};
3232

3333
#[derive(Debug, Clone, Copy)]
@@ -487,27 +487,28 @@ fn resolve_impl_trait_item<'db>(
487487
ns: Option<Namespace>,
488488
) -> Option<DocLinkDef> {
489489
let krate = ty.krate(db);
490-
let environment = crate::param_env_from_resolver(db, &resolver);
490+
let param_env = ty.param_env(db);
491491
let traits_in_scope = resolver.traits_in_scope(db);
492492

493493
// `ty.iterate_path_candidates()` require a scope, which is not available when resolving
494494
// attributes here. Use path resolution directly instead.
495495
//
496496
// FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
497-
let interner = DbInterner::new_with(db, environment.krate);
497+
let interner = DbInterner::new_with(db, param_env.krate);
498498
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
499499
let features = resolver.top_level_def_map().features();
500500
let ctx = MethodResolutionContext {
501501
infcx: &infcx,
502502
resolver: &resolver,
503-
param_env: environment.param_env,
503+
param_env: param_env.param_env,
504504
traits_in_scope: &traits_in_scope,
505-
edition: krate.edition(db),
505+
edition: krate.data(db).edition,
506506
features,
507507
call_span: hir_ty::Span::Dummy,
508508
receiver_span: hir_ty::Span::Dummy,
509509
};
510-
let resolution = ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty.ty);
510+
let resolution =
511+
ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty.ty.skip_binder());
511512
let resolution = match resolution {
512513
Ok(resolution) => resolution.item,
513514
Err(MethodError::PrivateMatch(resolution)) => resolution.item,

crates/hir/src/diagnostics.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ use hir_def::{
1515
};
1616
use hir_expand::{HirFileId, InFile, mod_path::ModPath, name::Name};
1717
use hir_ty::{
18-
CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, ParamEnvAndCrate,
19-
PathGenericsSource, PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
18+
CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, PathGenericsSource,
19+
PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
2020
db::HirDatabase,
2121
diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
2222
display::{DisplayTarget, HirDisplay},
23-
next_solver::DbInterner,
23+
next_solver::{DbInterner, EarlyBinder},
2424
solver_errors::SolverDiagnosticKind,
2525
};
2626
use stdx::{impl_from, never};
@@ -31,7 +31,7 @@ use syntax::{
3131
};
3232
use triomphe::Arc;
3333

34-
use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, Variant};
34+
use crate::{AssocItem, Field, Function, GenericDef, Local, Trait, Type, TypeOwnerId, Variant};
3535

3636
pub use hir_def::VariantId;
3737
pub use hir_ty::{
@@ -720,7 +720,7 @@ impl<'db> AnyDiagnostic<'db> {
720720
d: &'db InferenceDiagnostic,
721721
source_map: &hir_def::expr_store::BodySourceMap,
722722
sig_map: &hir_def::expr_store::ExpressionStoreSourceMap,
723-
env: ParamEnvAndCrate<'db>,
723+
type_owner: TypeOwnerId,
724724
) -> Option<AnyDiagnostic<'db>> {
725725
let expr_syntax = |expr| {
726726
source_map
@@ -744,6 +744,7 @@ impl<'db> AnyDiagnostic<'db> {
744744
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
745745
ExprOrPatId::PatId(pat) => pat_syntax(pat),
746746
};
747+
let generic_def = || def.generic_def(db);
747748
let span_syntax = |span| match span {
748749
hir_ty::Span::ExprId(idx) => expr_syntax(idx).map(|it| it.upcast()),
749750
hir_ty::Span::PatId(idx) => pat_syntax(idx).map(|it| it.upcast()),
@@ -795,8 +796,11 @@ impl<'db> AnyDiagnostic<'db> {
795796
}
796797
InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
797798
let call_expr = expr_syntax(*call_expr)?;
798-
ExpectedFunction { call: call_expr, found: Type::new(db, def, found.as_ref()) }
799-
.into()
799+
ExpectedFunction {
800+
call: call_expr,
801+
found: Type::new(generic_def(), found.as_ref()),
802+
}
803+
.into()
800804
}
801805
InferenceDiagnostic::UnresolvedField {
802806
expr,
@@ -808,7 +812,7 @@ impl<'db> AnyDiagnostic<'db> {
808812
UnresolvedField {
809813
expr,
810814
name: name.clone(),
811-
receiver: Type::new(db, def, receiver.as_ref()),
815+
receiver: Type::new(generic_def(), receiver.as_ref()),
812816
method_with_same_name_exists: *method_with_same_name_exists,
813817
}
814818
.into()
@@ -824,10 +828,10 @@ impl<'db> AnyDiagnostic<'db> {
824828
UnresolvedMethodCall {
825829
expr,
826830
name: name.clone(),
827-
receiver: Type::new(db, def, receiver.as_ref()),
831+
receiver: Type::new(generic_def(), receiver.as_ref()),
828832
field_with_same_name: field_with_same_name
829833
.as_ref()
830-
.map(|ty| Type::new(db, def, ty.as_ref())),
834+
.map(|ty| Type::new(generic_def(), ty.as_ref())),
831835
assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into),
832836
}
833837
.into()
@@ -857,7 +861,7 @@ impl<'db> AnyDiagnostic<'db> {
857861
}
858862
InferenceDiagnostic::TypedHole { expr, expected } => {
859863
let expr = expr_syntax(*expr)?;
860-
TypedHole { expr, expected: Type::new(db, def, expected.as_ref()) }.into()
864+
TypedHole { expr, expected: Type::new(generic_def(), expected.as_ref()) }.into()
861865
}
862866
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
863867
let InFile { file_id, value } = pat_syntax(pat)?;
@@ -868,12 +872,12 @@ impl<'db> AnyDiagnostic<'db> {
868872
}
869873
InferenceDiagnostic::CastToUnsized { expr, cast_ty } => {
870874
let expr = expr_syntax(*expr)?;
871-
CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.as_ref()) }.into()
875+
CastToUnsized { expr, cast_ty: Type::new(generic_def(), cast_ty.as_ref()) }.into()
872876
}
873877
InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => {
874878
let expr = expr_syntax(*expr)?;
875-
let expr_ty = Type::new(db, def, expr_ty.as_ref());
876-
let cast_ty = Type::new(db, def, cast_ty.as_ref());
879+
let expr_ty = Type::new(generic_def(), expr_ty.as_ref());
880+
let cast_ty = Type::new(generic_def(), cast_ty.as_ref());
877881
InvalidCast { expr, error: *error, expr_ty, cast_ty }.into()
878882
}
879883
InferenceDiagnostic::TyDiagnostic { source, diag } => {
@@ -946,10 +950,9 @@ impl<'db> AnyDiagnostic<'db> {
946950
&InferenceDiagnostic::TypeMustBeKnown { at_point, ref top_term } => {
947951
let at_point = span_syntax(at_point)?;
948952
let top_term = top_term.as_ref().map(|top_term| match top_term.as_ref().kind() {
949-
rustc_type_ir::GenericArgKind::Type(ty) => Either::Left(Type {
950-
ty,
951-
env: crate::body_param_env_from_has_crate(db, def),
952-
}),
953+
rustc_type_ir::GenericArgKind::Type(ty) => {
954+
Either::Left(Type::new(generic_def(), ty))
955+
}
953956
// FIXME: Printing the const to string is definitely not the correct thing to do here.
954957
rustc_type_ir::GenericArgKind::Const(konst) => Either::Right(
955958
konst.display(db, DisplayTarget::from_crate(db, def.krate(db))).to_string(),
@@ -968,14 +971,14 @@ impl<'db> AnyDiagnostic<'db> {
968971
let expr_or_pat = expr_or_pat_syntax(*node)?;
969972
TypeMismatch {
970973
expr_or_pat,
971-
expected: Type { env, ty: expected.as_ref() },
972-
actual: Type { env, ty: found.as_ref() },
974+
expected: Type { owner: type_owner, ty: EarlyBinder::bind(expected.as_ref()) },
975+
actual: Type { owner: type_owner, ty: EarlyBinder::bind(found.as_ref()) },
973976
}
974977
.into()
975978
}
976979
InferenceDiagnostic::SolverDiagnostic(d) => {
977980
let span = span_syntax(d.span)?;
978-
Self::solver_diagnostic(db, &d.kind, span, env)?
981+
Self::solver_diagnostic(db, &d.kind, span, type_owner)?
979982
}
980983
})
981984
}
@@ -984,16 +987,21 @@ impl<'db> AnyDiagnostic<'db> {
984987
db: &'db dyn HirDatabase,
985988
d: &'db SolverDiagnosticKind,
986989
span: SpanSyntax,
987-
env: ParamEnvAndCrate<'db>,
990+
type_owner: TypeOwnerId,
988991
) -> Option<AnyDiagnostic<'db>> {
989992
let interner = DbInterner::new_no_crate(db);
990993
Some(match d {
991994
SolverDiagnosticKind::TraitUnimplemented { trait_predicate, root_trait_predicate } => {
992-
let trait_predicate =
993-
crate::TraitPredicate { inner: trait_predicate.get(interner), env };
995+
let trait_predicate = crate::TraitPredicate {
996+
inner: trait_predicate.get(interner),
997+
owner: type_owner,
998+
};
994999
let root_trait_predicate =
9951000
root_trait_predicate.as_ref().map(|root_trait_predicate| {
996-
crate::TraitPredicate { inner: root_trait_predicate.get(interner), env }
1001+
crate::TraitPredicate {
1002+
inner: root_trait_predicate.get(interner),
1003+
owner: type_owner,
1004+
}
9971005
});
9981006
UnimplementedTrait { span, trait_predicate, root_trait_predicate }.into()
9991007
}

crates/hir/src/display.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
Adt, AnyFunctionId, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum,
3232
EnumVariant, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl,
3333
LifetimeParam, Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitPredicate,
34-
TraitRef, TupleField, Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union,
34+
TraitRef, TupleField, Type, TypeAlias, TypeOrConstParam, TypeParam, Union,
3535
};
3636

3737
fn write_builtin_derive_impl_method<'db>(
@@ -532,13 +532,7 @@ impl<'db> HirDisplay<'db> for EnumVariant {
532532

533533
impl<'db> HirDisplay<'db> for Type<'db> {
534534
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
535-
self.ty.hir_fmt(f)
536-
}
537-
}
538-
539-
impl<'db> HirDisplay<'db> for TypeNs<'db> {
540-
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
541-
self.ty.hir_fmt(f)
535+
self.ty.skip_binder().hir_fmt(f)
542536
}
543537
}
544538

@@ -578,7 +572,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
578572
let params = GenericParams::of(f.db, self.id.parent());
579573
let param_data = &params[self.id.local_id()];
580574
let krate = self.id.parent().krate(f.db).id;
581-
let ty = self.ty(f.db).ty;
575+
let ty = self.ty(f.db).ty.skip_binder();
582576
let predicates = GenericPredicates::query_all(f.db, self.id.parent());
583577
let predicates = predicates
584578
.iter_identity()

0 commit comments

Comments
 (0)