Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #149602 - lnicola:sync-from-ra, r=lnicola
`rust-analyzer` subtree update Subtree update of `rust-analyzer` to https://github.com/rust-lang/rust-analyzer/commit/633cff25206d5108043d87617a43c9d04aa42c88. Created using https://github.com/rust-lang/josh-sync. r? `@ghost`
bors 5 months ago
parent d8a9e86 · parent 633cff2 · commit c21e8e2
-rw-r--r--.github/workflows/rustdoc.yaml1
-rw-r--r--crates/hir-def/src/expr_store.rs2
-rw-r--r--crates/hir-def/src/hir/generics.rs2
-rw-r--r--crates/hir-def/src/lang_item.rs2
-rw-r--r--crates/hir-def/src/nameres.rs2
-rw-r--r--crates/hir-expand/src/files.rs2
-rw-r--r--crates/hir-expand/src/hygiene.rs8
-rw-r--r--crates/hir-expand/src/lib.rs4
-rw-r--r--crates/hir-ty/src/autoderef.rs37
-rw-r--r--crates/hir-ty/src/consteval.rs27
-rw-r--r--crates/hir-ty/src/db.rs24
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs12
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs22
-rw-r--r--crates/hir-ty/src/display.rs147
-rw-r--r--crates/hir-ty/src/drop.rs29
-rw-r--r--crates/hir-ty/src/infer.rs2
-rw-r--r--crates/hir-ty/src/infer/autoderef.rs4
-rw-r--r--crates/hir-ty/src/infer/closure.rs17
-rw-r--r--crates/hir-ty/src/infer/coerce.rs49
-rw-r--r--crates/hir-ty/src/infer/expr.rs36
-rw-r--r--crates/hir-ty/src/infer/op.rs2
-rw-r--r--crates/hir-ty/src/infer/opaques.rs2
-rw-r--r--crates/hir-ty/src/infer/path.rs4
-rw-r--r--crates/hir-ty/src/infer/place_op.rs2
-rw-r--r--crates/hir-ty/src/infer/unify.rs41
-rw-r--r--crates/hir-ty/src/inhabitedness.rs18
-rw-r--r--crates/hir-ty/src/layout.rs16
-rw-r--r--crates/hir-ty/src/layout/adt.rs8
-rw-r--r--crates/hir-ty/src/layout/tests.rs24
-rw-r--r--crates/hir-ty/src/lib.rs9
-rw-r--r--crates/hir-ty/src/lower.rs19
-rw-r--r--crates/hir-ty/src/method_resolution.rs48
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs2
-rw-r--r--crates/hir-ty/src/method_resolution/probe.rs8
-rw-r--r--crates/hir-ty/src/mir.rs6
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs16
-rw-r--r--crates/hir-ty/src/mir/eval.rs41
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs2
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs7
-rw-r--r--crates/hir-ty/src/mir/lower.rs18
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs26
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs4
-rw-r--r--crates/hir-ty/src/next_solver/predicate.rs4
-rw-r--r--crates/hir-ty/src/opaques.rs2
-rw-r--r--crates/hir-ty/src/specialization.rs6
-rw-r--r--crates/hir-ty/src/traits.rs61
-rw-r--r--crates/hir/src/attrs.rs6
-rw-r--r--crates/hir/src/display.rs78
-rw-r--r--crates/hir/src/has_source.rs2
-rw-r--r--crates/hir/src/lib.rs174
-rw-r--r--crates/hir/src/source_analyzer.rs26
-rw-r--r--crates/ide-assists/src/lib.rs2
-rw-r--r--crates/ide-completion/src/completions/keyword.rs54
-rw-r--r--crates/ide-completion/src/context/analysis.rs12
-rw-r--r--crates/ide-completion/src/item.rs2
-rw-r--r--crates/ide-completion/src/lib.rs3
-rw-r--r--crates/parser/src/lib.rs7
-rw-r--r--crates/paths/src/lib.rs4
-rw-r--r--crates/proc-macro-api/src/legacy_protocol/msg.rs185
-rw-r--r--crates/proc-macro-api/src/legacy_protocol/msg/flat.rs28
-rw-r--r--crates/proc-macro-srv/src/lib.rs29
-rw-r--r--crates/proc-macro-srv/src/token_stream.rs7
-rw-r--r--crates/project-model/src/cargo_workspace.rs2
-rw-r--r--crates/project-model/src/lib.rs7
-rw-r--r--crates/project-model/src/project_json.rs2
-rw-r--r--crates/project-model/src/workspace.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs9
-rw-r--r--crates/rust-analyzer/src/command.rs18
-rw-r--r--crates/rust-analyzer/src/discover.rs4
-rw-r--r--crates/rust-analyzer/src/global_state.rs26
-rw-r--r--crates/rust-analyzer/src/handlers/notification.rs2
-rw-r--r--crates/rust-analyzer/src/main_loop.rs89
-rw-r--r--crates/rust-analyzer/src/reload.rs4
-rw-r--r--crates/rust-analyzer/src/task_pool.rs14
-rw-r--r--crates/span/src/ast_id.rs3
-rw-r--r--crates/span/src/hygiene.rs4
-rw-r--r--crates/span/src/lib.rs27
-rw-r--r--crates/syntax/src/lib.rs2
-rw-r--r--crates/test-utils/src/assert_linear.rs2
-rw-r--r--crates/test-utils/src/fixture.rs13
-rw-r--r--docs/book/README.md1
-rw-r--r--docs/book/book.toml5
-rw-r--r--docs/book/src/contributing/README.md2
-rw-r--r--docs/book/src/contributing/architecture.md2
-rw-r--r--docs/book/src/contributing/guide.md2
-rw-r--r--docs/book/src/contributing/lsp-extensions.md2
-rw-r--r--docs/book/src/other_editors.md2
87 files changed, 920 insertions, 770 deletions
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml
index f975bbaa51..9cc18fc69e 100644
--- a/.github/workflows/rustdoc.yaml
+++ b/.github/workflows/rustdoc.yaml
@@ -8,6 +8,7 @@ env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTFLAGS: "-D warnings -W unreachable-pub"
+ RUSTDOCFLAGS: "-D warnings"
RUSTUP_MAX_RETRIES: 10
jobs:
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index 5695ab7ed0..66f7e25ffa 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -43,7 +43,7 @@ pub use self::lower::{
hir_assoc_type_binding_to_ast, hir_generic_arg_to_ast, hir_segment_to_ast_segment,
};
-/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
+/// A wrapper around [`span::SyntaxContext`] that is intended only for comparisons.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HygieneId(span::SyntaxContext);
diff --git a/crates/hir-def/src/hir/generics.rs b/crates/hir-def/src/hir/generics.rs
index 60cd66bf6b..1a2d5ebba4 100644
--- a/crates/hir-def/src/hir/generics.rs
+++ b/crates/hir-def/src/hir/generics.rs
@@ -20,7 +20,7 @@ pub type LocalLifetimeParamId = Idx<LifetimeParamData>;
/// Data about a generic type parameter (to a function, struct, impl, ...).
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeParamData {
- /// [`None`] only if the type ref is an [`TypeRef::ImplTrait`]. FIXME: Might be better to just
+ /// [`None`] only if the type ref is an [`crate::type_ref::TypeRef::ImplTrait`]. FIXME: Might be better to just
/// make it always be a value, giving impl trait a special name.
pub name: Option<Name>,
pub default: Option<TypeRefId>,
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 3f2cf09e21..04acb8b712 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -238,7 +238,7 @@ language_item_table! { LangItems =>
Clone, sym::clone, clone_trait, TraitId, GenericRequirement::None;
Sync, sym::sync, sync_trait, TraitId, GenericRequirement::Exact(0);
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, TraitId, GenericRequirement::None;
- /// The associated item of the [`DiscriminantKind`] trait.
+ /// The associated item of the `DiscriminantKind` trait.
Discriminant, sym::discriminant_type, discriminant_type, TypeAliasId, GenericRequirement::None;
PointeeTrait, sym::pointee_trait, pointee_trait, TraitId, GenericRequirement::None;
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 5f45e188e0..aefbf6306e 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -739,7 +739,7 @@ impl ModuleData {
self.origin.definition_source(db)
}
- /// Same as [`definition_source`] but only returns the file id to prevent parsing the ASt.
+ /// Same as [`ModuleData::definition_source`] but only returns the file id to prevent parsing the ASt.
pub fn definition_source_file_id(&self) -> HirFileId {
match self.origin {
ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs
index fe557d6802..fce92c8a3e 100644
--- a/crates/hir-expand/src/files.rs
+++ b/crates/hir-expand/src/files.rs
@@ -295,7 +295,7 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> {
/// Falls back to the macro call range if the node cannot be mapped up fully.
///
/// For attributes and derives, this will point back to the attribute only.
- /// For the entire item use [`InFile::original_file_range_full`].
+ /// For the entire item use `InFile::original_file_range_full`.
pub fn original_file_range_rooted(self, db: &dyn db::ExpandDatabase) -> FileRange {
self.borrow().map(SyntaxNode::text_range).original_node_file_range_rooted(db)
}
diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs
index 28800c6fab..bd6f7e4f2b 100644
--- a/crates/hir-expand/src/hygiene.rs
+++ b/crates/hir-expand/src/hygiene.rs
@@ -8,9 +8,9 @@
//!
//! # The Expansion Order Hierarchy
//!
-//! `ExpnData` in rustc, rust-analyzer's version is [`MacroCallLoc`]. Traversing the hierarchy
-//! upwards can be achieved by walking up [`MacroCallLoc::kind`]'s contained file id, as
-//! [`MacroFile`]s are interned [`MacroCallLoc`]s.
+//! `ExpnData` in rustc, rust-analyzer's version is `MacroCallLoc`. Traversing the hierarchy
+//! upwards can be achieved by walking up `MacroCallLoc::kind`'s contained file id, as
+//! `MacroFile`s are interned `MacroCallLoc`s.
//!
//! # The Macro Definition Hierarchy
//!
@@ -18,7 +18,7 @@
//!
//! # The Call-site Hierarchy
//!
-//! `ExpnData::call_site` in rustc, [`MacroCallLoc::call_site`] in rust-analyzer.
+//! `ExpnData::call_site` in rustc, `MacroCallLoc::call_site` in rust-analyzer.
// FIXME: Move this into the span crate? Not quite possible today as that depends on `MacroCallLoc`
// which contains a bunch of unrelated things
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 157a5310bd..c92e41f507 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -4,6 +4,8 @@
//! tree originates not from the text of some `FileId`, but from some macro
//! expansion.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
+// It's useful to refer to code that is private in doc comments.
+#![allow(rustdoc::private_intra_doc_links)]
pub use intern;
@@ -860,7 +862,7 @@ impl ExpansionInfo {
}
/// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
- /// Unlike [`map_range_down_exact`], this will consider spans that contain the given span.
+ /// Unlike [`ExpansionInfo::map_range_down_exact`], this will consider spans that contain the given span.
///
/// Note this does a linear search through the entire backing vector of the spanmap.
pub fn map_range_down(
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index 0a36c0e726..abab3bfb25 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -8,10 +8,9 @@ use std::fmt;
use hir_def::{TraitId, TypeAliasId};
use rustc_type_ir::inherent::{IntoKind, Ty as _};
use tracing::debug;
-use triomphe::Arc;
use crate::{
- TraitEnvironment,
+ ParamEnvAndCrate,
db::HirDatabase,
infer::InferenceContext,
next_solver::{
@@ -35,13 +34,13 @@ const AUTODEREF_RECURSION_LIMIT: usize = 20;
/// detects a cycle in the deref chain.
pub fn autoderef<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
ty: Canonical<'db, Ty<'db>>,
) -> impl Iterator<Item = Ty<'db>> + use<'db> {
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let (ty, _) = infcx.instantiate_canonical(&ty);
- let autoderef = Autoderef::new(&infcx, &env, ty);
+ let autoderef = Autoderef::new(&infcx, env.param_env, ty);
let mut v = Vec::new();
for (ty, _steps) in autoderef {
// `ty` may contain unresolved inference variables. Since there's no chance they would be
@@ -111,12 +110,12 @@ struct AutoderefTraits {
// borrows it.
pub(crate) trait AutoderefCtx<'db> {
fn infcx(&self) -> &InferCtxt<'db>;
- fn env(&self) -> &TraitEnvironment<'db>;
+ fn param_env(&self) -> ParamEnv<'db>;
}
pub(crate) struct DefaultAutoderefCtx<'a, 'db> {
infcx: &'a InferCtxt<'db>,
- env: &'a TraitEnvironment<'db>,
+ param_env: ParamEnv<'db>,
}
impl<'db> AutoderefCtx<'db> for DefaultAutoderefCtx<'_, 'db> {
#[inline]
@@ -124,8 +123,8 @@ impl<'db> AutoderefCtx<'db> for DefaultAutoderefCtx<'_, 'db> {
self.infcx
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- self.env
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.param_env
}
}
@@ -136,8 +135,8 @@ impl<'db> AutoderefCtx<'db> for InferenceContextAutoderefCtx<'_, '_, 'db> {
&self.0.table.infer_ctxt
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- &self.0.table.trait_env
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.0.table.param_env
}
}
@@ -201,7 +200,7 @@ where
// autoderef expect this type to have been structurally normalized.
if let TyKind::Alias(..) = ty.kind() {
let (normalized_ty, obligations) =
- structurally_normalize_ty(self.infcx(), self.env().env, ty)?;
+ structurally_normalize_ty(self.infcx(), self.param_env(), ty)?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
@@ -231,10 +230,10 @@ impl<'a, 'db> Autoderef<'a, 'db> {
#[inline]
pub(crate) fn new_with_tracking(
infcx: &'a InferCtxt<'db>,
- env: &'a TraitEnvironment<'db>,
+ param_env: ParamEnv<'db>,
base_ty: Ty<'db>,
) -> Self {
- Self::new_impl(DefaultAutoderefCtx { infcx, env }, base_ty)
+ Self::new_impl(DefaultAutoderefCtx { infcx, param_env }, base_ty)
}
}
@@ -257,10 +256,10 @@ impl<'a, 'db> Autoderef<'a, 'db, usize> {
#[inline]
pub(crate) fn new(
infcx: &'a InferCtxt<'db>,
- env: &'a TraitEnvironment<'db>,
+ param_env: ParamEnv<'db>,
base_ty: Ty<'db>,
) -> Self {
- Self::new_impl(DefaultAutoderefCtx { infcx, env }, base_ty)
+ Self::new_impl(DefaultAutoderefCtx { infcx, param_env }, base_ty)
}
}
@@ -292,8 +291,8 @@ where
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- self.ctx.env()
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.ctx.param_env()
}
#[inline]
@@ -339,7 +338,7 @@ where
let trait_ref = TraitRef::new(interner, trait_.into(), [ty]);
let obligation =
- Obligation::new(interner, ObligationCause::new(), self.env().env, trait_ref);
+ Obligation::new(interner, ObligationCause::new(), self.param_env(), trait_ref);
// We detect whether the self type implements `Deref` before trying to
// structurally normalize. We use `predicate_may_hold_opaque_types_jank`
// to support not-yet-defined opaque types. It will succeed for `impl Deref`
@@ -351,7 +350,7 @@ where
let (normalized_ty, obligations) = structurally_normalize_ty(
self.infcx(),
- self.env().env,
+ self.param_env(),
Ty::new_projection(interner, trait_target.into(), [ty]),
)?;
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 65250f94c2..012632aa55 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -5,7 +5,7 @@ mod tests;
use base_db::Crate;
use hir_def::{
- ConstId, EnumVariantId, GeneralConstId, StaticId,
+ ConstId, EnumVariantId, GeneralConstId, HasModule, StaticId,
attrs::AttrFlags,
expr_store::Body,
hir::{Expr, ExprId},
@@ -16,14 +16,14 @@ use rustc_type_ir::inherent::IntoKind;
use triomphe::Arc;
use crate::{
- LifetimeElisionKind, MemoryMap, TraitEnvironment, TyLoweringContext,
+ LifetimeElisionKind, MemoryMap, ParamEnvAndCrate, TyLoweringContext,
db::HirDatabase,
display::DisplayTarget,
infer::InferenceContext,
mir::{MirEvalError, MirLowerError},
next_solver::{
- Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Ty,
- ValueConst,
+ Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
+ ParamEnv, Ty, ValueConst,
},
};
@@ -85,7 +85,7 @@ pub fn intern_const_ref<'a>(
krate: Crate,
) -> Const<'a> {
let interner = DbInterner::new_no_crate(db);
- let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate));
+ let layout = db.layout_of_ty(ty, ParamEnvAndCrate { param_env: ParamEnv::empty(), krate });
let kind = match value {
LiteralConstRef::Int(i) => {
// FIXME: We should handle failure of layout better.
@@ -207,7 +207,7 @@ pub(crate) fn const_eval_discriminant_variant<'db>(
let mir_body = db.monomorphized_mir_body(
def,
GenericArgs::new_from_iter(interner, []),
- db.trait_environment_for_body(def),
+ ParamEnvAndCrate { param_env: db.trait_environment_for_body(def), krate: def.krate(db) },
)?;
let c = interpret_mir(db, mir_body, false, None)?.0?;
let c = if is_signed {
@@ -259,7 +259,7 @@ pub(crate) fn const_eval_cycle_result<'db>(
_: &'db dyn HirDatabase,
_: ConstId,
_: GenericArgs<'db>,
- _: Option<Arc<TraitEnvironment<'db>>>,
+ _: Option<ParamEnvAndCrate<'db>>,
) -> Result<Const<'db>, ConstEvalError<'db>> {
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
}
@@ -282,9 +282,13 @@ pub(crate) fn const_eval_query<'db>(
db: &'db dyn HirDatabase,
def: ConstId,
subst: GenericArgs<'db>,
- trait_env: Option<Arc<TraitEnvironment<'db>>>,
+ trait_env: Option<ParamEnvAndCrate<'db>>,
) -> Result<Const<'db>, ConstEvalError<'db>> {
- let body = db.monomorphized_mir_body(def.into(), subst, db.trait_environment(def.into()))?;
+ let body = db.monomorphized_mir_body(
+ def.into(),
+ subst,
+ ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) },
+ )?;
let c = interpret_mir(db, body, false, trait_env)?.0?;
Ok(c)
}
@@ -297,7 +301,10 @@ pub(crate) fn const_eval_static_query<'db>(
let body = db.monomorphized_mir_body(
def.into(),
GenericArgs::new_from_iter(interner, []),
- db.trait_environment_for_body(def.into()),
+ ParamEnvAndCrate {
+ param_env: db.trait_environment_for_body(def.into()),
+ krate: def.krate(db),
+ },
)?;
let c = interpret_mir(db, body, false, None)?.0?;
Ok(c)
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index df058711a6..f9523e7168 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -12,13 +12,16 @@ use salsa::plumbing::AsId;
use triomphe::Arc;
use crate::{
- ImplTraitId, TraitEnvironment, TyDefId, ValueTyDefId,
+ ImplTraitId, TyDefId, ValueTyDefId,
consteval::ConstEvalError,
dyn_compatibility::DynCompatibilityViolation,
layout::{Layout, LayoutError},
lower::{Diagnostics, GenericDefaults},
mir::{BorrowckResult, MirBody, MirLowerError},
- next_solver::{Const, EarlyBinder, GenericArgs, PolyFnSig, TraitRef, Ty, VariancesOf},
+ next_solver::{
+ Const, EarlyBinder, GenericArgs, ParamEnv, PolyFnSig, TraitRef, Ty, VariancesOf,
+ },
+ traits::ParamEnvAndCrate,
};
#[query_group::query_group]
@@ -46,7 +49,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'db self,
def: DefWithBodyId,
subst: GenericArgs<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)]
@@ -54,7 +57,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'db self,
def: InternedClosureId,
subst: GenericArgs<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>;
#[salsa::invoke(crate::mir::borrowck_query)]
@@ -70,7 +73,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'db self,
def: ConstId,
subst: GenericArgs<'db>,
- trait_env: Option<Arc<TraitEnvironment<'db>>>,
+ trait_env: Option<ParamEnvAndCrate<'db>>,
) -> Result<Const<'db>, ConstEvalError<'db>>;
#[salsa::invoke(crate::consteval::const_eval_static_query)]
@@ -88,7 +91,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::transparent]
fn lookup_impl_method<'db>(
&'db self,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
func: FunctionId,
fn_subst: GenericArgs<'db>,
) -> (FunctionId, GenericArgs<'db>);
@@ -101,7 +104,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'db self,
def: AdtId,
args: GenericArgs<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::layout_of_ty_query)]
@@ -109,7 +112,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn layout_of_ty<'db>(
&'db self,
ty: Ty<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)]
@@ -186,11 +189,10 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
#[salsa::transparent]
- fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId)
- -> Arc<TraitEnvironment<'db>>;
+ fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId) -> ParamEnv<'db>;
#[salsa::invoke(crate::lower::trait_environment_query)]
- fn trait_environment<'db>(&'db self, def: GenericDefId) -> Arc<TraitEnvironment<'db>>;
+ fn trait_environment<'db>(&'db self, def: GenericDefId) -> ParamEnv<'db>;
#[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
#[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)]
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index ffbcea4d25..0de7fab8d1 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -25,7 +25,7 @@ use triomphe::Arc;
use typed_arena::Arena;
use crate::{
- Adjust, InferenceResult, TraitEnvironment,
+ Adjust, InferenceResult,
db::HirDatabase,
diagnostics::match_check::{
self,
@@ -33,7 +33,7 @@ use crate::{
},
display::{DisplayTarget, HirDisplay},
next_solver::{
- DbInterner, Ty, TyKind, TypingMode,
+ DbInterner, ParamEnv, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
};
@@ -79,7 +79,7 @@ impl BodyValidationDiagnostic {
let infer = InferenceResult::for_body(db, owner);
let body = db.body(owner);
let env = db.trait_environment_for_body(owner);
- let interner = DbInterner::new_with(db, env.krate);
+ let interner = DbInterner::new_with(db, owner.krate(db));
let infcx =
interner.infer_ctxt().build(TypingMode::typeck_for_body(interner, owner.into()));
let mut validator = ExprValidator {
@@ -100,7 +100,7 @@ struct ExprValidator<'db> {
owner: DefWithBodyId,
body: Arc<Body>,
infer: &'db InferenceResult<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
diagnostics: Vec<BodyValidationDiagnostic>,
validate_lints: bool,
infcx: InferCtxt<'db>,
@@ -210,7 +210,7 @@ impl<'db> ExprValidator<'db> {
return;
}
- let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env.clone());
+ let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env);
let pattern_arena = Arena::new();
let mut m_arms = Vec::with_capacity(arms.len());
@@ -332,7 +332,7 @@ impl<'db> ExprValidator<'db> {
return;
};
let pattern_arena = Arena::new();
- let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env.clone());
+ let cx = MatchCheckCtx::new(self.owner.module(self.db()), &self.infcx, self.env);
for stmt in &**statements {
let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else {
continue;
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index c70c6b6119..e7ee7c62b9 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -14,14 +14,12 @@ use rustc_pattern_analysis::{
use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike};
use smallvec::{SmallVec, smallvec};
use stdx::never;
-use triomphe::Arc;
use crate::{
- TraitEnvironment,
db::HirDatabase,
inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
next_solver::{
- Ty, TyKind,
+ ParamEnv, Ty, TyKind,
infer::{InferCtxt, traits::ObligationCause},
},
};
@@ -76,16 +74,12 @@ pub(crate) struct MatchCheckCtx<'a, 'db> {
module: ModuleId,
pub(crate) db: &'db dyn HirDatabase,
exhaustive_patterns: bool,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
infcx: &'a InferCtxt<'db>,
}
impl<'a, 'db> MatchCheckCtx<'a, 'db> {
- pub(crate) fn new(
- module: ModuleId,
- infcx: &'a InferCtxt<'db>,
- env: Arc<TraitEnvironment<'db>>,
- ) -> Self {
+ pub(crate) fn new(module: ModuleId, infcx: &'a InferCtxt<'db>, env: ParamEnv<'db>) -> Self {
let db = infcx.interner.db;
let def_map = module.crate_def_map(db);
let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
@@ -114,7 +108,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> {
}
fn is_uninhabited(&self, ty: Ty<'db>) -> bool {
- is_ty_uninhabited_from(self.infcx, ty, self.module, self.env.clone())
+ is_ty_uninhabited_from(self.infcx, ty, self.module, self.env)
}
/// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
@@ -159,7 +153,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> {
let ty = field_tys[fid].instantiate(self.infcx.interner, substs);
let ty = self
.infcx
- .at(&ObligationCause::dummy(), self.env.env)
+ .at(&ObligationCause::dummy(), self.env)
.deeply_normalize(ty)
.unwrap_or(ty);
(fid, ty)
@@ -446,11 +440,7 @@ impl<'a, 'db> PatCx for MatchCheckCtx<'a, 'db> {
let mut variants = IndexVec::with_capacity(enum_data.variants.len());
for &(variant, _, _) in enum_data.variants.iter() {
let is_uninhabited = is_enum_variant_uninhabited_from(
- cx.infcx,
- variant,
- subst,
- cx.module,
- self.env.clone(),
+ cx.infcx, variant, subst, cx.module, self.env,
);
let visibility = if is_uninhabited {
VariantVisibility::Empty
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index c76b8dc5f0..16c2922731 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -44,10 +44,9 @@ use rustc_type_ir::{
use smallvec::SmallVec;
use span::Edition;
use stdx::never;
-use triomphe::Arc;
use crate::{
- CallableDefId, FnAbi, ImplTraitId, InferenceResult, MemoryMap, TraitEnvironment, consteval,
+ CallableDefId, FnAbi, ImplTraitId, InferenceResult, MemoryMap, ParamEnvAndCrate, consteval,
db::{HirDatabase, InternedClosure, InternedCoroutine},
generics::generics,
layout::Layout,
@@ -55,8 +54,8 @@ use crate::{
mir::pad16,
next_solver::{
AliasTy, Clause, ClauseKind, Const, ConstKind, DbInterner, EarlyBinder,
- ExistentialPredicate, FnSig, GenericArg, GenericArgs, PolyFnSig, Region, SolverDefId, Term,
- TraitRef, Ty, TyKind, TypingMode,
+ ExistentialPredicate, FnSig, GenericArg, GenericArgs, ParamEnv, PolyFnSig, Region,
+ SolverDefId, Term, TraitRef, Ty, TyKind, TypingMode,
abi::Safety,
infer::{DbInternerInferExt, traits::ObligationCause},
},
@@ -64,6 +63,8 @@ use crate::{
utils::{detect_variant_from_bytes, fn_traits},
};
+pub type Result<T = (), E = HirDisplayError> = std::result::Result<T, E>;
+
pub trait HirWrite: fmt::Write {
fn start_location_link(&mut self, _location: ModuleDefId) {}
fn end_location_link(&mut self) {}
@@ -191,7 +192,7 @@ impl<'db> HirFormatter<'_, 'db> {
}
pub trait HirDisplay<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError>;
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result;
/// Returns a `Display`able type that is human-readable.
fn into_displayable<'a>(
@@ -400,7 +401,7 @@ impl<'db> HirFormatter<'_, 'db> {
&mut self,
iter: impl IntoIterator<Item = T>,
sep: &str,
- ) -> Result<(), HirDisplayError> {
+ ) -> Result {
let mut first = true;
for e in iter {
if !first {
@@ -419,7 +420,7 @@ impl<'db> HirFormatter<'_, 'db> {
}
/// This allows using the `write!` macro directly with a `HirFormatter`.
- pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<(), HirDisplayError> {
+ pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result {
// We write to a buffer first to track output size
self.buf.clear();
fmt::write(&mut self.buf, args)?;
@@ -429,12 +430,12 @@ impl<'db> HirFormatter<'_, 'db> {
self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
}
- pub fn write_str(&mut self, s: &str) -> Result<(), HirDisplayError> {
+ pub fn write_str(&mut self, s: &str) -> Result {
self.fmt.write_str(s)?;
Ok(())
}
- pub fn write_char(&mut self, c: char) -> Result<(), HirDisplayError> {
+ pub fn write_char(&mut self, c: char) -> Result {
self.fmt.write_char(c)?;
Ok(())
}
@@ -542,7 +543,7 @@ pub enum ClosureStyle {
}
impl<'db, T: HirDisplay<'db>> HirDisplayWrapper<'_, 'db, T> {
- pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
+ pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result {
let krate = self.display_target.krate;
let interner = DbInterner::new_with(self.db, krate);
self.t.hir_fmt(&mut HirFormatter {
@@ -595,21 +596,18 @@ where
const TYPE_HINT_TRUNCATION: &str = "…";
impl<'db, T: HirDisplay<'db>> HirDisplay<'db> for &T {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
HirDisplay::hir_fmt(*self, f)
}
}
impl<'db, T: HirDisplay<'db> + Internable> HirDisplay<'db> for Interned<T> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
HirDisplay::hir_fmt(self.as_ref(), f)
}
}
-fn write_projection<'db>(
- f: &mut HirFormatter<'_, 'db>,
- alias: &AliasTy<'db>,
-) -> Result<(), HirDisplayError> {
+fn write_projection<'db>(f: &mut HirFormatter<'_, 'db>, alias: &AliasTy<'db>) -> Result {
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
}
@@ -666,7 +664,7 @@ fn write_projection<'db>(
}
impl<'db> HirDisplay<'db> for GenericArg<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self {
GenericArg::Ty(ty) => ty.hir_fmt(f),
GenericArg::Lifetime(lt) => lt.hir_fmt(f),
@@ -676,7 +674,7 @@ impl<'db> HirDisplay<'db> for GenericArg<'db> {
}
impl<'db> HirDisplay<'db> for Const<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.kind() {
ConstKind::Placeholder(_) => write!(f, "<placeholder>"),
ConstKind::Bound(BoundVarIndexKind::Bound(db), bound_const) => {
@@ -715,11 +713,11 @@ fn render_const_scalar<'db>(
b: &[u8],
memory_map: &MemoryMap<'db>,
ty: Ty<'db>,
-) -> Result<(), HirDisplayError> {
- let trait_env = TraitEnvironment::empty(f.krate());
+) -> Result {
+ let param_env = ParamEnv::empty();
let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let ty = infcx.at(&ObligationCause::new(), trait_env.env).deeply_normalize(ty).unwrap_or(ty);
- render_const_scalar_inner(f, b, memory_map, ty, trait_env)
+ let ty = infcx.at(&ObligationCause::new(), param_env).deeply_normalize(ty).unwrap_or(ty);
+ render_const_scalar_inner(f, b, memory_map, ty, param_env)
}
fn render_const_scalar_inner<'db>(
@@ -727,9 +725,10 @@ fn render_const_scalar_inner<'db>(
b: &[u8],
memory_map: &MemoryMap<'db>,
ty: Ty<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
-) -> Result<(), HirDisplayError> {
+ param_env: ParamEnv<'db>,
+) -> Result {
use TyKind;
+ let param_env = ParamEnvAndCrate { param_env, krate: f.krate() };
match ty.kind() {
TyKind::Bool => write!(f, "{}", b[0] != 0),
TyKind::Char => {
@@ -792,7 +791,7 @@ fn render_const_scalar_inner<'db>(
TyKind::Slice(ty) => {
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
- let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, param_env) else {
return f.write_str("<layout-error>");
};
let size_one = layout.size.bytes_usize();
@@ -826,7 +825,7 @@ fn render_const_scalar_inner<'db>(
let Ok(t) = memory_map.vtable_ty(ty_id) else {
return f.write_str("<ty-missing-in-vtable-map>");
};
- let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(t, param_env) else {
return f.write_str("<layout-error>");
};
let size = layout.size.bytes_usize();
@@ -856,7 +855,7 @@ fn render_const_scalar_inner<'db>(
return f.write_str("<layout-error>");
}
});
- let Ok(layout) = f.db.layout_of_ty(t, trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(t, param_env) else {
return f.write_str("<layout-error>");
};
let size = layout.size.bytes_usize();
@@ -868,7 +867,7 @@ fn render_const_scalar_inner<'db>(
}
},
TyKind::Tuple(tys) => {
- let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, param_env) else {
return f.write_str("<layout-error>");
};
f.write_str("(")?;
@@ -880,7 +879,7 @@ fn render_const_scalar_inner<'db>(
f.write_str(", ")?;
}
let offset = layout.fields.offset(id).bytes_usize();
- let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, param_env) else {
f.write_str("<layout-error>")?;
continue;
};
@@ -891,7 +890,7 @@ fn render_const_scalar_inner<'db>(
}
TyKind::Adt(def, args) => {
let def = def.def_id().0;
- let Ok(layout) = f.db.layout_of_adt(def, args, trait_env.clone()) else {
+ let Ok(layout) = f.db.layout_of_adt(def, args, param_env) else {
return f.write_str("<layout-error>");
};
match def {
@@ -914,7 +913,7 @@ fn render_const_scalar_inner<'db>(
write!(f, "{}", f.db.union_signature(u).name.display(f.db, f.edition()))
}
hir_def::AdtId::EnumId(e) => {
- let Ok(target_data_layout) = f.db.target_data_layout(trait_env.krate) else {
+ let Ok(target_data_layout) = f.db.target_data_layout(f.krate()) else {
return f.write_str("<target-layout-not-available>");
};
let Some((var_id, var_layout)) =
@@ -954,7 +953,7 @@ fn render_const_scalar_inner<'db>(
let Some(len) = consteval::try_const_usize(f.db, len) else {
return f.write_str("<unknown-array-len>");
};
- let Ok(layout) = f.db.layout_of_ty(ty, trait_env) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, param_env) else {
return f.write_str("<layout-error>");
};
let size_one = layout.size.bytes_usize();
@@ -995,18 +994,19 @@ fn render_variant_after_name<'db>(
data: &VariantFields,
f: &mut HirFormatter<'_, 'db>,
field_types: &ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ param_env: ParamEnv<'db>,
layout: &Layout,
args: GenericArgs<'db>,
b: &[u8],
memory_map: &MemoryMap<'db>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
+ let param_env = ParamEnvAndCrate { param_env, krate: f.krate() };
match data.shape {
FieldsShape::Record | FieldsShape::Tuple => {
let render_field = |f: &mut HirFormatter<'_, 'db>, id: LocalFieldId| {
let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
let ty = field_types[id].instantiate(f.interner, args);
- let Ok(layout) = f.db.layout_of_ty(ty, trait_env.clone()) else {
+ let Ok(layout) = f.db.layout_of_ty(ty, param_env) else {
return f.write_str("<layout-error>");
};
let size = layout.size.bytes_usize();
@@ -1043,10 +1043,7 @@ fn render_variant_after_name<'db>(
}
impl<'db> HirDisplay<'db> for Ty<'db> {
- fn hir_fmt(
- &self,
- f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_, 'db>,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_, 'db>) -> Result {
let interner = f.interner;
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
@@ -1649,7 +1646,7 @@ fn hir_fmt_generics<'db>(
parameters: &[GenericArg<'db>],
generic_def: Option<hir_def::GenericDefId>,
self_: Option<Ty<'db>>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
if parameters.is_empty() {
return Ok(());
}
@@ -1699,7 +1696,7 @@ fn hir_fmt_generic_args<'db>(
parameters: &[GenericArg<'db>],
generic_def: Option<hir_def::GenericDefId>,
self_: Option<Ty<'db>>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
if parameters.is_empty() {
return Ok(());
}
@@ -1719,7 +1716,7 @@ fn hir_fmt_generic_arguments<'db>(
f: &mut HirFormatter<'_, 'db>,
parameters: &[GenericArg<'db>],
self_: Option<Ty<'db>>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
let mut first = true;
let lifetime_offset = parameters.iter().position(|arg| arg.region().is_some());
@@ -1743,7 +1740,7 @@ fn hir_fmt_tys<'db>(
f: &mut HirFormatter<'_, 'db>,
tys: &[Ty<'db>],
self_: Option<Ty<'db>>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
let mut first = true;
for ty in tys {
@@ -1759,7 +1756,7 @@ fn hir_fmt_tys<'db>(
}
impl<'db> HirDisplay<'db> for PolyFnSig<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let FnSig { inputs_and_output, c_variadic, safety, abi: _ } = self.skip_binder();
if let Safety::Unsafe = safety {
write!(f, "unsafe ")?;
@@ -1790,7 +1787,7 @@ impl<'db> HirDisplay<'db> for PolyFnSig<'db> {
}
impl<'db> HirDisplay<'db> for Term<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self {
Term::Ty(it) => it.hir_fmt(f),
Term::Const(it) => it.hir_fmt(f),
@@ -1822,7 +1819,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix<'db>(
this: Either<Ty<'db>, Region<'db>>,
predicates: &[Clause<'db>],
default_sized: SizedByDefault,
-) -> Result<(), HirDisplayError> {
+) -> Result {
write!(f, "{prefix}")?;
if !predicates.is_empty()
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
@@ -1839,7 +1836,7 @@ fn write_bounds_like_dyn_trait<'db>(
this: Either<Ty<'db>, Region<'db>>,
predicates: &[Clause<'db>],
default_sized: SizedByDefault,
-) -> Result<(), HirDisplayError> {
+) -> Result {
// Note: This code is written to produce nice results (i.e.
// corresponding to surface Rust) for types that can occur in
// actual Rust. It will have weird results if the predicates
@@ -1983,7 +1980,7 @@ fn write_bounds_like_dyn_trait<'db>(
}
impl<'db> HirDisplay<'db> for TraitRef<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let trait_ = self.def_id.0;
f.start_location_link(trait_.into());
write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
@@ -1994,7 +1991,7 @@ impl<'db> HirDisplay<'db> for TraitRef<'db> {
}
impl<'db> HirDisplay<'db> for Region<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.kind() {
RegionKind::ReEarlyParam(param) => {
let generics = generics(f.db, param.id.parent);
@@ -2028,7 +2025,7 @@ pub fn write_visibility<'db>(
module_id: ModuleId,
vis: Visibility,
f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
match vis {
Visibility::Public => write!(f, "pub "),
Visibility::PubCrate(_) => write!(f, "pub(crate) "),
@@ -2051,21 +2048,13 @@ pub fn write_visibility<'db>(
}
pub trait HirDisplayWithExpressionStore<'db> {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError>;
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result;
}
impl<'db, T: ?Sized + HirDisplayWithExpressionStore<'db>> HirDisplayWithExpressionStore<'db>
for &'_ T
{
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
T::hir_fmt(&**self, f, store)
}
}
@@ -2086,16 +2075,12 @@ impl<'a, T> ExpressionStoreAdapter<'a, T> {
}
impl<'db, T: HirDisplayWithExpressionStore<'db>> HirDisplay<'db> for ExpressionStoreAdapter<'_, T> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
T::hir_fmt(&self.0, f, self.1)
}
}
impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
match &store[*self] {
LifetimeRef::Named(name) => write!(f, "{}", name.display(f.db, f.edition())),
LifetimeRef::Static => write!(f, "'static"),
@@ -2114,11 +2099,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for LifetimeRefId {
}
impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
match &store[*self] {
TypeRef::Never => write!(f, "!")?,
TypeRef::TypeParam(param) => {
@@ -2243,11 +2224,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeRefId {
}
impl<'db> HirDisplayWithExpressionStore<'db> for ConstRef {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- _store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, _store: &ExpressionStore) -> Result {
// FIXME
write!(f, "{{const}}")?;
@@ -2256,11 +2233,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for ConstRef {
}
impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
match self {
&TypeBound::Path(path, modifier) => {
match modifier {
@@ -2300,11 +2273,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for TypeBound {
}
impl<'db> HirDisplayWithExpressionStore<'db> for Path {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
match (self.type_anchor(), self.kind()) {
(Some(anchor), _) => {
write!(f, "<")?;
@@ -2452,11 +2421,7 @@ impl<'db> HirDisplayWithExpressionStore<'db> for Path {
}
impl<'db> HirDisplayWithExpressionStore<'db> for hir_def::expr_store::path::GenericArg {
- fn hir_fmt(
- &self,
- f: &mut HirFormatter<'_, 'db>,
- store: &ExpressionStore,
- ) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>, store: &ExpressionStore) -> Result {
match self {
hir_def::expr_store::path::GenericArg::Type(ty) => ty.hir_fmt(f, store),
hir_def::expr_store::path::GenericArg::Const(_c) => {
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index d76de4b8ca..def3c44927 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -4,13 +4,12 @@ use hir_def::{AdtId, signatures::StructFlags};
use rustc_hash::FxHashSet;
use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike};
use stdx::never;
-use triomphe::Arc;
use crate::{
- InferenceResult, TraitEnvironment, consteval,
+ InferenceResult, consteval,
method_resolution::TraitImpls,
next_solver::{
- DbInterner, SimplifiedType, Ty, TyKind,
+ DbInterner, ParamEnv, SimplifiedType, Ty, TyKind,
infer::{InferCtxt, traits::ObligationCause},
obligation_ctxt::ObligationCtxt,
},
@@ -47,22 +46,18 @@ pub enum DropGlue {
HasDropGlue,
}
-pub fn has_drop_glue<'db>(
- infcx: &InferCtxt<'db>,
- ty: Ty<'db>,
- env: Arc<TraitEnvironment<'db>>,
-) -> DropGlue {
+pub fn has_drop_glue<'db>(infcx: &InferCtxt<'db>, ty: Ty<'db>, env: ParamEnv<'db>) -> DropGlue {
has_drop_glue_impl(infcx, ty, env, &mut FxHashSet::default())
}
fn has_drop_glue_impl<'db>(
infcx: &InferCtxt<'db>,
ty: Ty<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
visited: &mut FxHashSet<Ty<'db>>,
) -> DropGlue {
let mut ocx = ObligationCtxt::new(infcx);
- let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty);
+ let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, ty).unwrap_or(ty);
if !visited.insert(ty) {
// Recursive type.
@@ -91,7 +86,7 @@ fn has_drop_glue_impl<'db>(
has_drop_glue_impl(
infcx,
field_ty.instantiate(infcx.interner, subst),
- env.clone(),
+ env,
visited,
)
})
@@ -111,7 +106,7 @@ fn has_drop_glue_impl<'db>(
has_drop_glue_impl(
infcx,
field_ty.instantiate(infcx.interner, subst),
- env.clone(),
+ env,
visited,
)
})
@@ -124,7 +119,7 @@ fn has_drop_glue_impl<'db>(
}
TyKind::Tuple(tys) => tys
.iter()
- .map(|ty| has_drop_glue_impl(infcx, ty, env.clone(), visited))
+ .map(|ty| has_drop_glue_impl(infcx, ty, env, visited))
.max()
.unwrap_or(DropGlue::None),
TyKind::Array(ty, len) => {
@@ -142,9 +137,7 @@ fn has_drop_glue_impl<'db>(
let env = db.trait_environment_for_body(owner);
captures
.iter()
- .map(|capture| {
- has_drop_glue_impl(infcx, capture.ty(db, subst), env.clone(), visited)
- })
+ .map(|capture| has_drop_glue_impl(infcx, capture.ty(db, subst), env, visited))
.max()
.unwrap_or(DropGlue::None)
}
@@ -169,14 +162,14 @@ fn has_drop_glue_impl<'db>(
| TyKind::Placeholder(..) => DropGlue::None,
TyKind::Dynamic(..) => DropGlue::HasDropGlue,
TyKind::Alias(..) => {
- if infcx.type_is_copy_modulo_regions(env.env, ty) {
+ if infcx.type_is_copy_modulo_regions(env, ty) {
DropGlue::None
} else {
DropGlue::HasDropGlue
}
}
TyKind::Param(_) => {
- if infcx.type_is_copy_modulo_regions(env.env, ty) {
+ if infcx.type_is_copy_modulo_regions(env, ty) {
DropGlue::None
} else {
DropGlue::DependOnParams
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index ab173799bc..cafe032969 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -944,7 +944,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
resolver: Resolver<'db>,
) -> Self {
let trait_env = db.trait_environment_for_body(owner);
- let table = unify::InferenceTable::new(db, trait_env, Some(owner));
+ let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));
let types = InternedStandardTypes::new(table.interner());
InferenceContext {
result: InferenceResult::new(types.error),
diff --git a/crates/hir-ty/src/infer/autoderef.rs b/crates/hir-ty/src/infer/autoderef.rs
index 1af102af23..b54a6cdee2 100644
--- a/crates/hir-ty/src/infer/autoderef.rs
+++ b/crates/hir-ty/src/infer/autoderef.rs
@@ -16,11 +16,11 @@ use crate::{
impl<'db> InferenceTable<'db> {
pub(crate) fn autoderef(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db, usize> {
- Autoderef::new(&self.infer_ctxt, &self.trait_env, base_ty)
+ Autoderef::new(&self.infer_ctxt, self.param_env, base_ty)
}
pub(crate) fn autoderef_with_tracking(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db> {
- Autoderef::new_with_tracking(&self.infer_ctxt, &self.trait_env, base_ty)
+ Autoderef::new_with_tracking(&self.infer_ctxt, self.param_env, base_ty)
}
}
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 89ebd2b21d..14b0c9076c 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -367,7 +367,7 @@ impl<'db> InferenceContext<'_, 'db> {
_ = self
.table
.infer_ctxt
- .at(&ObligationCause::new(), self.table.trait_env.env)
+ .at(&ObligationCause::new(), self.table.param_env)
.eq(inferred_fnptr_sig, generalized_fnptr_sig)
.map(|infer_ok| self.table.register_infer_ok(infer_ok));
@@ -749,19 +749,18 @@ impl<'db> InferenceContext<'_, 'db> {
{
// Check that E' = S'.
let cause = ObligationCause::new();
- let InferOk { value: (), obligations } = table
- .infer_ctxt
- .at(&cause, table.trait_env.env)
- .eq(expected_ty, supplied_ty)?;
+ let InferOk { value: (), obligations } =
+ table.infer_ctxt.at(&cause, table.param_env).eq(expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
}
let supplied_output_ty = supplied_sig.output();
let cause = ObligationCause::new();
- let InferOk { value: (), obligations } = table
- .infer_ctxt
- .at(&cause, table.trait_env.env)
- .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
+ let InferOk { value: (), obligations } =
+ table
+ .infer_ctxt
+ .at(&cause, table.param_env)
+ .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
all_obligations.extend(obligations);
let inputs = supplied_sig
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index df24148920..77c7155550 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -50,10 +50,9 @@ use rustc_type_ir::{
};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
-use triomphe::Arc;
use crate::{
- Adjust, Adjustment, AutoBorrow, PointerCast, TargetFeatures, TraitEnvironment,
+ Adjust, Adjustment, AutoBorrow, ParamEnvAndCrate, PointerCast, TargetFeatures,
autoderef::Autoderef,
db::{HirDatabase, InternedClosureId},
infer::{
@@ -62,7 +61,7 @@ use crate::{
next_solver::{
Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper,
Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed,
- GenericArgs, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
+ GenericArgs, ParamEnv, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
TypingMode,
infer::{
DbInternerInferExt, InferCtxt, InferOk, InferResult,
@@ -77,7 +76,7 @@ use crate::{
trait CoerceDelegate<'db> {
fn infcx(&self) -> &InferCtxt<'db>;
- fn env(&self) -> &TraitEnvironment<'db>;
+ fn param_env(&self) -> ParamEnv<'db>;
fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget);
fn set_diverging(&mut self, diverging_ty: Ty<'db>);
@@ -137,8 +136,8 @@ where
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- self.delegate.env()
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.delegate.param_env()
}
#[inline]
@@ -169,7 +168,7 @@ where
fn unify_raw(&self, a: Ty<'db>, b: Ty<'db>) -> InferResult<'db, Ty<'db>> {
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
self.infcx().commit_if_ok(|_| {
- let at = self.infcx().at(&self.cause, self.env().env);
+ let at = self.infcx().at(&self.cause, self.param_env());
let res = if self.use_lub {
at.lub(b, a)
@@ -329,7 +328,7 @@ where
obligations.push(Obligation::new(
self.interner(),
self.cause.clone(),
- self.env().env,
+ self.param_env(),
Binder::dummy(PredicateKind::Coerce(CoercePredicate {
a: source_ty,
b: target_ty,
@@ -381,7 +380,7 @@ where
let mut first_error = None;
let mut r_borrow_var = None;
- let mut autoderef = Autoderef::new_with_tracking(self.infcx(), self.env(), a);
+ let mut autoderef = Autoderef::new_with_tracking(self.infcx(), self.param_env(), a);
let mut found = None;
for (referent_ty, autoderefs) in autoderef.by_ref() {
@@ -684,7 +683,7 @@ where
let mut queue: SmallVec<[PredicateObligation<'db>; 4]> = smallvec![Obligation::new(
self.interner(),
cause,
- self.env().env,
+ self.param_env(),
TraitRef::new(
self.interner(),
coerce_unsized_did.into(),
@@ -975,8 +974,8 @@ impl<'db> CoerceDelegate<'db> for InferenceCoercionDelegate<'_, '_, 'db> {
&self.0.table.infer_ctxt
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- &self.0.table.trait_env
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.0.table.param_env
}
#[inline]
@@ -1104,12 +1103,8 @@ impl<'db> InferenceContext<'_, 'db> {
match self.table.commit_if_ok(|table| {
// We need to eagerly handle nested obligations due to lazy norm.
let mut ocx = ObligationCtxt::new(&table.infer_ctxt);
- let value = ocx.lub(
- &ObligationCause::new(),
- table.trait_env.env,
- prev_ty,
- new_ty,
- )?;
+ let value =
+ ocx.lub(&ObligationCause::new(), table.param_env, prev_ty, new_ty)?;
if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else {
@@ -1152,7 +1147,7 @@ impl<'db> InferenceContext<'_, 'db> {
let sig = self
.table
.infer_ctxt
- .at(&ObligationCause::new(), self.table.trait_env.env)
+ .at(&ObligationCause::new(), self.table.param_env)
.lub(a_sig, b_sig)
.map(|ok| self.table.register_infer_ok(ok))?;
@@ -1231,7 +1226,7 @@ impl<'db> InferenceContext<'_, 'db> {
.commit_if_ok(|table| {
table
.infer_ctxt
- .at(&ObligationCause::new(), table.trait_env.env)
+ .at(&ObligationCause::new(), table.param_env)
.lub(prev_ty, new_ty)
})
.unwrap_err())
@@ -1483,7 +1478,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
//
// Another example is `break` with no argument expression.
assert!(expression_ty.is_unit(), "if let hack without unit type");
- icx.table.infer_ctxt.at(cause, icx.table.trait_env.env).eq(expected, found).map(
+ icx.table.infer_ctxt.at(cause, icx.table.param_env).eq(expected, found).map(
|infer_ok| {
icx.table.register_infer_ok(infer_ok);
expression_ty
@@ -1540,7 +1535,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
pub fn could_coerce<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> bool {
coerce(db, env, tys).is_ok()
@@ -1548,7 +1543,7 @@ pub fn could_coerce<'db>(
struct HirCoercionDelegate<'a, 'db> {
infcx: &'a InferCtxt<'db>,
- env: &'a TraitEnvironment<'db>,
+ param_env: ParamEnv<'db>,
target_features: &'a TargetFeatures<'db>,
}
@@ -1558,8 +1553,8 @@ impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> {
self.infcx
}
#[inline]
- fn env(&self) -> &TraitEnvironment<'db> {
- self.env
+ fn param_env(&self) -> ParamEnv<'db> {
+ self.param_env
}
fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
(self.target_features, TargetFeatureIsSafeInTarget::No)
@@ -1573,7 +1568,7 @@ impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> {
fn coerce<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), TypeError<DbInterner<'db>>> {
let interner = DbInterner::new_with(db, env.krate);
@@ -1586,7 +1581,7 @@ fn coerce<'db>(
let mut coerce = Coerce {
delegate: HirCoercionDelegate {
infcx: &infcx,
- env: &env,
+ param_env: env.param_env,
target_features: &target_features,
},
cause,
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 01508b0f9b..4e1711e48e 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -4,7 +4,7 @@ use std::{iter::repeat_with, mem};
use either::Either;
use hir_def::{
- BlockId, FieldId, GenericDefId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+ FieldId, GenericDefId, ItemContainerId, Lookup, TupleFieldId, TupleId,
expr_store::path::{GenericArgs as HirGenericArgs, Path},
hir::{
Array, AsmOperand, AsmOptions, BinaryOp, BindingAnnotation, Expr, ExprId, ExprOrPatId,
@@ -23,7 +23,7 @@ use syntax::ast::RangeOp;
use tracing::debug;
use crate::{
- Adjust, Adjustment, CallableDefId, DeclContext, DeclOrigin, Rawness, TraitEnvironment,
+ Adjust, Adjustment, CallableDefId, DeclContext, DeclOrigin, Rawness,
autoderef::InferenceContextAutoderef,
consteval,
db::InternedCoroutine,
@@ -377,11 +377,11 @@ impl<'db> InferenceContext<'_, 'db> {
);
self.types.bool
}
- Expr::Block { statements, tail, label, id } => {
- self.infer_block(tgt_expr, *id, statements, *tail, *label, expected)
+ Expr::Block { statements, tail, label, id: _ } => {
+ self.infer_block(tgt_expr, statements, *tail, *label, expected)
}
- Expr::Unsafe { id, statements, tail } => {
- self.infer_block(tgt_expr, *id, statements, *tail, None, expected)
+ Expr::Unsafe { id: _, statements, tail } => {
+ self.infer_block(tgt_expr, statements, *tail, None, expected)
}
Expr::Const(id) => {
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
@@ -389,8 +389,8 @@ impl<'db> InferenceContext<'_, 'db> {
})
.1
}
- Expr::Async { id, statements, tail } => {
- self.infer_async_block(tgt_expr, id, statements, tail)
+ Expr::Async { id: _, statements, tail } => {
+ self.infer_async_block(tgt_expr, statements, tail)
}
&Expr::Loop { body, label } => {
// FIXME: should be:
@@ -1167,7 +1167,6 @@ impl<'db> InferenceContext<'_, 'db> {
fn infer_async_block(
&mut self,
tgt_expr: ExprId,
- id: &Option<BlockId>,
statements: &[Statement],
tail: &Option<ExprId>,
) -> Ty<'db> {
@@ -1179,7 +1178,7 @@ impl<'db> InferenceContext<'_, 'db> {
// FIXME: We should handle async blocks like we handle closures
let expected = &Expectation::has_type(ret_ty);
let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
- let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected);
+ let ty = this.infer_block(tgt_expr, statements, *tail, None, expected);
if let Some(target) = expected.only_has_type(&mut this.table) {
match this.coerce(tgt_expr.into(), ty, target, AllowTwoPhase::No, ExprIsRead::Yes) {
Ok(res) => res,
@@ -1447,7 +1446,6 @@ impl<'db> InferenceContext<'_, 'db> {
fn infer_block(
&mut self,
expr: ExprId,
- block_id: Option<BlockId>,
statements: &[Statement],
tail: Option<ExprId>,
label: Option<LabelId>,
@@ -1455,11 +1453,6 @@ impl<'db> InferenceContext<'_, 'db> {
) -> Ty<'db> {
let coerce_ty = expected.coercion_target_type(&mut self.table);
let g = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
- let prev_env = block_id.map(|block_id| {
- let prev_env = self.table.trait_env.clone();
- TraitEnvironment::with_block(&mut self.table.trait_env, block_id);
- prev_env
- });
let (break_ty, ty) =
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty), label, |this| {
@@ -1566,9 +1559,6 @@ impl<'db> InferenceContext<'_, 'db> {
}
});
self.resolver.reset_to_guard(g);
- if let Some(prev_env) = prev_env {
- self.table.trait_env = prev_env;
- }
break_ty.unwrap_or(ty)
}
@@ -1974,7 +1964,7 @@ impl<'db> InferenceContext<'_, 'db> {
// is polymorphic) and the expected return type.
// No argument expectations are produced if unification fails.
let origin = ObligationCause::new();
- ocx.sup(&origin, self.table.trait_env.env, expected_output, formal_output)?;
+ ocx.sup(&origin, self.table.param_env, expected_output, formal_output)?;
if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch);
}
@@ -2066,7 +2056,7 @@ impl<'db> InferenceContext<'_, 'db> {
let formal_ty_error = this
.table
.infer_ctxt
- .at(&ObligationCause::new(), this.table.trait_env.env)
+ .at(&ObligationCause::new(), this.table.param_env)
.eq(formal_input_ty, coerced_ty);
// If neither check failed, the types are compatible
@@ -2143,7 +2133,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.db,
GenericDefId::from_callable(self.db, fn_def.0),
);
- let param_env = self.table.trait_env.env;
+ let param_env = self.table.param_env;
self.table.register_predicates(clauses_as_obligations(
generic_predicates.iter_instantiated_copied(self.interner(), parameters.as_slice()),
ObligationCause::new(),
@@ -2162,7 +2152,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.table.register_predicate(Obligation::new(
self.interner(),
ObligationCause::new(),
- self.table.trait_env.env,
+ self.table.param_env,
TraitRef::new(self.interner(), trait_.into(), substs),
));
}
diff --git a/crates/hir-ty/src/infer/op.rs b/crates/hir-ty/src/infer/op.rs
index 6fbac8f5ae..8236de167f 100644
--- a/crates/hir-ty/src/infer/op.rs
+++ b/crates/hir-ty/src/infer/op.rs
@@ -343,7 +343,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
let obligation = Obligation::new(
self.interner(),
cause,
- self.table.trait_env.env,
+ self.table.param_env,
TraitRef::new_from_args(self.interner(), trait_did.into(), args),
);
let mut ocx = ObligationCtxt::new(self.infcx());
diff --git a/crates/hir-ty/src/infer/opaques.rs b/crates/hir-ty/src/infer/opaques.rs
index ba4b53a0d7..ce4597f83d 100644
--- a/crates/hir-ty/src/infer/opaques.rs
+++ b/crates/hir-ty/src/infer/opaques.rs
@@ -136,7 +136,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
let cause = ObligationCause::new();
- let at = self.table.infer_ctxt.at(&cause, self.table.trait_env.env);
+ let at = self.table.infer_ctxt.at(&cause, self.table.param_env);
let hidden_type = match at.deeply_normalize(hidden_type) {
Ok(hidden_type) => hidden_type,
Err(_errors) => OpaqueHiddenType { ty: self.types.error },
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 6e3d15893f..301cbf462c 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -224,7 +224,7 @@ impl<'db> InferenceContext<'_, 'db> {
) {
let interner = self.interner();
let predicates = GenericPredicates::query_all(self.db, def);
- let param_env = self.table.trait_env.env;
+ let param_env = self.table.param_env;
self.table.register_predicates(clauses_as_obligations(
predicates.iter_instantiated_copied(interner, subst.as_slice()),
ObligationCause::new(),
@@ -343,7 +343,7 @@ impl<'db> InferenceContext<'_, 'db> {
self.table.register_predicate(Obligation::new(
self.interner(),
ObligationCause::new(),
- self.table.trait_env.env,
+ self.table.param_env,
trait_ref,
));
args
diff --git a/crates/hir-ty/src/infer/place_op.rs b/crates/hir-ty/src/infer/place_op.rs
index 9544fb449f..3ef5e5870a 100644
--- a/crates/hir-ty/src/infer/place_op.rs
+++ b/crates/hir-ty/src/infer/place_op.rs
@@ -124,7 +124,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
ctx.table.register_predicate(Obligation::new(
ctx.interner(),
ObligationCause::new(),
- ctx.table.trait_env.env,
+ ctx.table.param_env,
ClauseKind::ConstArgHasType(ct, ctx.types.usize),
));
self_ty = Ty::new_slice(ctx.interner(), element_ty);
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index bc3c46341c..a5060416a1 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -2,6 +2,7 @@
use std::fmt;
+use base_db::Crate;
use hir_def::{AdtId, DefWithBodyId, GenericParamId};
use hir_expand::name::Name;
use intern::sym;
@@ -12,15 +13,13 @@ use rustc_type_ir::{
solve::Certainty,
};
use smallvec::SmallVec;
-use triomphe::Arc;
use crate::{
- TraitEnvironment,
db::HirDatabase,
next_solver::{
AliasTy, Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg,
- GenericArgs, Goal, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty,
- TyKind, TypingMode,
+ GenericArgs, Goal, ParamEnv, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef,
+ Ty, TyKind, TypingMode,
fulfill::{FulfillmentCtxt, NextSolverError},
infer::{
DbInternerInferExt, InferCtxt, InferOk, InferResult,
@@ -32,7 +31,8 @@ use crate::{
obligation_ctxt::ObligationCtxt,
},
traits::{
- FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt,
+ FnTrait, NextTraitSolveResult, ParamEnvAndCrate, next_trait_solve_canonical_in_ctxt,
+ next_trait_solve_in_ctxt,
},
};
@@ -89,7 +89,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
/// unresolved goal `T = U`.
pub fn could_unify<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> bool {
could_unify_impl(db, env, tys, |ctxt| ctxt.try_evaluate_obligations())
@@ -101,7 +101,7 @@ pub fn could_unify<'db>(
/// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U`
pub fn could_unify_deeply<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> bool {
could_unify_impl(db, env, tys, |ctxt| ctxt.evaluate_obligations_error_on_ambiguity())
@@ -109,14 +109,14 @@ pub fn could_unify_deeply<'db>(
fn could_unify_impl<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
select: for<'a> fn(&mut ObligationCtxt<'a, 'db>) -> Vec<NextSolverError<'db>>,
) -> bool {
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let cause = ObligationCause::dummy();
- let at = infcx.at(&cause, env.env);
+ let at = infcx.at(&cause, env.param_env);
let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(tys);
let mut ctxt = ObligationCtxt::new(&infcx);
let can_unify = at
@@ -129,7 +129,7 @@ fn could_unify_impl<'db>(
#[derive(Clone)]
pub(crate) struct InferenceTable<'db> {
pub(crate) db: &'db dyn HirDatabase,
- pub(crate) trait_env: Arc<TraitEnvironment<'db>>,
+ pub(crate) param_env: ParamEnv<'db>,
pub(crate) infer_ctxt: InferCtxt<'db>,
pub(super) fulfillment_cx: FulfillmentCtxt<'db>,
pub(super) diverging_type_vars: FxHashSet<Ty<'db>>,
@@ -145,10 +145,11 @@ impl<'db> InferenceTable<'db> {
/// Outside it, always pass `owner = None`.
pub(crate) fn new(
db: &'db dyn HirDatabase,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnv<'db>,
+ krate: Crate,
owner: Option<DefWithBodyId>,
) -> Self {
- let interner = DbInterner::new_with(db, trait_env.krate);
+ let interner = DbInterner::new_with(db, krate);
let typing_mode = match owner {
Some(owner) => TypingMode::typeck_for_body(interner, owner.into()),
// IDE things wants to reveal opaque types.
@@ -157,7 +158,7 @@ impl<'db> InferenceTable<'db> {
let infer_ctxt = interner.infer_ctxt().build(typing_mode);
InferenceTable {
db,
- trait_env,
+ param_env: trait_env,
fulfillment_cx: FulfillmentCtxt::new(&infer_ctxt),
infer_ctxt,
diverging_type_vars: FxHashSet::default(),
@@ -170,7 +171,7 @@ impl<'db> InferenceTable<'db> {
}
pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'db>) -> bool {
- self.infer_ctxt.type_is_copy_modulo_regions(self.trait_env.env, ty)
+ self.infer_ctxt.type_is_copy_modulo_regions(self.param_env, ty)
}
pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool {
@@ -272,7 +273,7 @@ impl<'db> InferenceTable<'db> {
pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> {
self.infer_ctxt
- .at(&ObligationCause::new(), self.trait_env.env)
+ .at(&ObligationCause::new(), self.param_env)
.structurally_normalize_ty(alias, &mut self.fulfillment_cx)
.unwrap_or(alias)
}
@@ -332,7 +333,7 @@ impl<'db> InferenceTable<'db> {
}
pub(crate) fn at<'a>(&'a self, cause: &'a ObligationCause) -> At<'a, 'db> {
- self.infer_ctxt.at(cause, self.trait_env.env)
+ self.infer_ctxt.at(cause, self.param_env)
}
pub(crate) fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
@@ -374,7 +375,7 @@ impl<'db> InferenceTable<'db> {
// in a reentrant borrow, causing an ICE.
let result = self
.infer_ctxt
- .at(&ObligationCause::misc(), self.trait_env.env)
+ .at(&ObligationCause::misc(), self.param_env)
.structurally_normalize_ty(ty, &mut self.fulfillment_cx);
match result {
Ok(normalized_ty) => normalized_ty,
@@ -422,14 +423,14 @@ impl<'db> InferenceTable<'db> {
/// choice (during e.g. method resolution or deref).
#[tracing::instrument(level = "debug", skip(self))]
pub(crate) fn try_obligation(&mut self, predicate: Predicate<'db>) -> NextTraitSolveResult {
- let goal = Goal { param_env: self.trait_env.env, predicate };
+ let goal = Goal { param_env: self.param_env, predicate };
let canonicalized = self.canonicalize(goal);
next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized)
}
pub(crate) fn register_obligation(&mut self, predicate: Predicate<'db>) {
- let goal = Goal { param_env: self.trait_env.env, predicate };
+ let goal = Goal { param_env: self.param_env, predicate };
self.register_obligation_in_env(goal)
}
@@ -486,7 +487,7 @@ impl<'db> InferenceTable<'db> {
self.register_predicate(Obligation::new(
self.interner(),
cause,
- self.trait_env.env,
+ self.param_env,
ClauseKind::WellFormed(term),
));
}
diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs
index 5e742bba3e..075a7066db 100644
--- a/crates/hir-ty/src/inhabitedness.rs
+++ b/crates/hir-ty/src/inhabitedness.rs
@@ -7,14 +7,12 @@ use rustc_type_ir::{
TypeSuperVisitable, TypeVisitable, TypeVisitor,
inherent::{AdtDef, IntoKind},
};
-use triomphe::Arc;
use crate::{
- TraitEnvironment,
consteval::try_const_usize,
db::HirDatabase,
next_solver::{
- DbInterner, EarlyBinder, GenericArgs, Ty, TyKind,
+ DbInterner, EarlyBinder, GenericArgs, ParamEnv, Ty, TyKind,
infer::{InferCtxt, traits::ObligationCause},
obligation_ctxt::ObligationCtxt,
},
@@ -26,7 +24,7 @@ pub(crate) fn is_ty_uninhabited_from<'db>(
infcx: &InferCtxt<'db>,
ty: Ty<'db>,
target_mod: ModuleId,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
) -> bool {
let _p = tracing::info_span!("is_ty_uninhabited_from", ?ty).entered();
let mut uninhabited_from = UninhabitedFrom::new(infcx, target_mod, env);
@@ -41,7 +39,7 @@ pub(crate) fn is_enum_variant_uninhabited_from<'db>(
variant: EnumVariantId,
subst: GenericArgs<'db>,
target_mod: ModuleId,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
) -> bool {
let _p = tracing::info_span!("is_enum_variant_uninhabited_from").entered();
@@ -56,7 +54,7 @@ struct UninhabitedFrom<'a, 'db> {
// guard for preventing stack overflow in non trivial non terminating types
max_depth: usize,
infcx: &'a InferCtxt<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
}
const CONTINUE_OPAQUELY_INHABITED: ControlFlow<VisiblyUninhabited> = Continue(());
@@ -78,7 +76,7 @@ impl<'db> TypeVisitor<DbInterner<'db>> for UninhabitedFrom<'_, 'db> {
if matches!(ty.kind(), TyKind::Alias(..)) {
let mut ocx = ObligationCtxt::new(self.infcx);
- match ocx.structurally_normalize_ty(&ObligationCause::dummy(), self.env.env, ty) {
+ match ocx.structurally_normalize_ty(&ObligationCause::dummy(), self.env, ty) {
Ok(it) => ty = it,
Err(_) => return CONTINUE_OPAQUELY_INHABITED,
}
@@ -101,11 +99,7 @@ impl<'db> TypeVisitor<DbInterner<'db>> for UninhabitedFrom<'_, 'db> {
}
impl<'a, 'db> UninhabitedFrom<'a, 'db> {
- fn new(
- infcx: &'a InferCtxt<'db>,
- target_mod: ModuleId,
- env: Arc<TraitEnvironment<'db>>,
- ) -> Self {
+ fn new(infcx: &'a InferCtxt<'db>, target_mod: ModuleId, env: ParamEnv<'db>) -> Self {
Self { target_mod, recursive_ty: FxHashSet::default(), max_depth: 500, infcx, env }
}
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 97660a67ef..565063fb13 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -21,7 +21,7 @@ use rustc_type_ir::{
use triomphe::Arc;
use crate::{
- InferenceResult, TraitEnvironment,
+ InferenceResult, ParamEnvAndCrate,
consteval::try_const_usize,
db::HirDatabase,
next_solver::{
@@ -131,7 +131,7 @@ fn layout_of_simd_ty<'db>(
id: StructId,
repr_packed: bool,
args: &GenericArgs<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
dl: &TargetDataLayout,
) -> Result<Arc<Layout>, LayoutError> {
// Supported SIMD vectors are homogeneous ADTs with exactly one array field:
@@ -159,7 +159,7 @@ fn layout_of_simd_ty<'db>(
pub fn layout_of_ty_query<'db>(
db: &'db dyn HirDatabase,
ty: Ty<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError> {
let krate = trait_env.krate;
let interner = DbInterner::new_with(db, krate);
@@ -248,10 +248,8 @@ pub fn layout_of_ty_query<'db>(
let kind =
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
- let fields = tys
- .iter()
- .map(|k| db.layout_of_ty(k, trait_env.clone()))
- .collect::<Result<Vec<_>, _>>()?;
+ let fields =
+ tys.iter().map(|k| db.layout_of_ty(k, trait_env)).collect::<Result<Vec<_>, _>>()?;
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
let fields = fields.iter().collect::<IndexVec<_, _>>();
cx.calc.univariant(&fields, &ReprOptions::default(), kind)?
@@ -329,7 +327,7 @@ pub fn layout_of_ty_query<'db>(
.map(|it| {
let ty =
it.ty.instantiate(interner, args.split_closure_args_untupled().parent_args);
- db.layout_of_ty(ty, trait_env.clone())
+ db.layout_of_ty(ty, trait_env)
})
.collect::<Result<Vec<_>, _>>()?;
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
@@ -362,7 +360,7 @@ pub fn layout_of_ty_query<'db>(
pub(crate) fn layout_of_ty_cycle_result<'db>(
_: &dyn HirDatabase,
_: Ty<'db>,
- _: Arc<TraitEnvironment<'db>>,
+ _: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError> {
Err(LayoutError::RecursiveTypeWithoutIndirection)
}
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index ecebf7935d..cf2d0989fd 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -13,7 +13,7 @@ use smallvec::SmallVec;
use triomphe::Arc;
use crate::{
- TraitEnvironment,
+ ParamEnvAndCrate,
db::HirDatabase,
layout::{Layout, LayoutCx, LayoutError, field_ty},
next_solver::GenericArgs,
@@ -23,7 +23,7 @@ pub fn layout_of_adt_query<'db>(
db: &'db dyn HirDatabase,
def: AdtId,
args: GenericArgs<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError> {
let krate = trait_env.krate;
let Ok(target) = db.target_data_layout(krate) else {
@@ -34,7 +34,7 @@ pub fn layout_of_adt_query<'db>(
let handle_variant = |def: VariantId, var: &VariantFields| {
var.fields()
.iter()
- .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &args), trait_env.clone()))
+ .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &args), trait_env))
.collect::<Result<Vec<_>, _>>()
};
let (variants, repr, is_special_no_niche) = match def {
@@ -99,7 +99,7 @@ pub(crate) fn layout_of_adt_cycle_result<'db>(
_: &'db dyn HirDatabase,
_def: AdtId,
_args: GenericArgs<'db>,
- _trait_env: Arc<TraitEnvironment<'db>>,
+ _trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<Layout>, LayoutError> {
Err(LayoutError::RecursiveTypeWithoutIndirection)
}
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 878813a696..43215253ba 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -1,6 +1,6 @@
use base_db::target::TargetData;
use either::Either;
-use hir_def::db::DefDatabase;
+use hir_def::{HasModule, db::DefDatabase};
use project_model::{Sysroot, toolchain_info::QueryConfig};
use rustc_hash::FxHashMap;
use rustc_type_ir::inherent::GenericArgs as _;
@@ -9,7 +9,7 @@ use test_fixture::WithFixture;
use triomphe::Arc;
use crate::{
- InferenceResult,
+ InferenceResult, ParamEnvAndCrate,
db::HirDatabase,
layout::{Layout, LayoutError},
next_solver::{DbInterner, GenericArgs},
@@ -90,13 +90,15 @@ fn eval_goal(
),
Either::Right(ty_id) => db.ty(ty_id.into()).instantiate_identity(),
};
- db.layout_of_ty(
- goal_ty,
- db.trait_environment(match adt_or_type_alias_id {
- Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
- Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
- }),
- )
+ let param_env = db.trait_environment(match adt_or_type_alias_id {
+ Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
+ Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
+ });
+ let krate = match adt_or_type_alias_id {
+ Either::Left(it) => it.krate(&db),
+ Either::Right(it) => it.krate(&db),
+ };
+ db.layout_of_ty(goal_ty, ParamEnvAndCrate { param_env, krate })
})
}
@@ -139,7 +141,9 @@ fn eval_expr(
.0;
let infer = InferenceResult::for_body(&db, function_id.into());
let goal_ty = infer.type_of_binding[b];
- db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
+ let param_env = db.trait_environment(function_id.into());
+ let krate = function_id.krate(&db);
+ db.layout_of_ty(goal_ty, ParamEnvAndCrate { param_env, krate })
})
}
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 6d3adec6a8..5ebe87c5d5 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -2,6 +2,8 @@
//! information and various assists.
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
+// It's useful to refer to code that is private in doc comments.
+#![allow(rustdoc::private_intra_doc_links)]
// FIXME: We used to import `rustc_*` deps from `rustc_private` with `feature = "in-rust-tree" but
// temporarily switched to crates.io versions due to hardships that working on them from rustc
@@ -67,7 +69,6 @@ use rustc_type_ir::{
};
use syntax::ast::{ConstArg, make};
use traits::FnTrait;
-use triomphe::Arc;
use crate::{
db::HirDatabase,
@@ -94,7 +95,7 @@ pub use lower::{
};
pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db};
pub use target_feature::TargetFeatures;
-pub use traits::{TraitEnvironment, check_orphan_rules};
+pub use traits::{ParamEnvAndCrate, check_orphan_rules};
pub use utils::{
TargetFeatureIsSafeInTarget, Unsafety, all_super_traits, direct_super_traits,
is_fn_unsafe_to_call, target_feature_is_safe_in_target,
@@ -474,10 +475,10 @@ where
/// To be used from `hir` only.
pub fn callable_sig_from_fn_trait<'db>(
self_ty: Ty<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
db: &'db dyn HirDatabase,
) -> Option<(FnTrait, PolyFnSig<'db>)> {
- let mut table = InferenceTable::new(db, trait_env.clone(), None);
+ let mut table = InferenceTable::new(db, trait_env.param_env, trait_env.krate, None);
let lang_items = table.interner().lang_items();
let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?;
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index cfd2a06b2a..301e89556d 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -53,7 +53,7 @@ use tracing::debug;
use triomphe::{Arc, ThinArc};
use crate::{
- FnAbi, ImplTraitId, TraitEnvironment, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
+ FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
consteval::intern_const_ref,
db::{HirDatabase, InternedOpaqueTyId},
generics::{Generics, generics, trait_self_param_idx},
@@ -1743,10 +1743,9 @@ impl<'db> GenericPredicates<'db> {
pub(crate) fn trait_environment_for_body_query(
db: &dyn HirDatabase,
def: DefWithBodyId,
-) -> Arc<TraitEnvironment<'_>> {
+) -> ParamEnv<'_> {
let Some(def) = def.as_generic_def_id(db) else {
- let krate = def.module(db).krate();
- return TraitEnvironment::empty(krate);
+ return ParamEnv::empty();
};
db.trait_environment(def)
}
@@ -1754,24 +1753,16 @@ pub(crate) fn trait_environment_for_body_query(
pub(crate) fn trait_environment_query<'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
-) -> Arc<TraitEnvironment<'db>> {
+) -> ParamEnv<'db> {
let module = def.module(db);
let interner = DbInterner::new_with(db, module.krate());
let predicates = GenericPredicates::query_all(db, def);
- let traits_in_scope = predicates
- .iter_identity_copied()
- .filter_map(|pred| match pred.kind().skip_binder() {
- ClauseKind::Trait(tr) => Some((tr.self_ty(), tr.def_id().0)),
- _ => None,
- })
- .collect();
let clauses = rustc_type_ir::elaborate::elaborate(interner, predicates.iter_identity_copied());
let clauses = Clauses::new_from_iter(interner, clauses);
- let env = ParamEnv { clauses };
// FIXME: We should normalize projections here, like rustc does.
- TraitEnvironment::new(module.krate(), module.containing_block(), traits_in_scope, env)
+ ParamEnv { clauses }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 9a6adedb99..a5ec2a3fec 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -32,13 +32,13 @@ use stdx::impl_from;
use triomphe::Arc;
use crate::{
- TraitEnvironment, all_super_traits,
+ all_super_traits,
db::HirDatabase,
infer::{InferenceContext, unify::InferenceTable},
lower::GenericPredicates,
next_solver::{
- Binder, ClauseKind, DbInterner, FnSig, GenericArgs, PredicateKind, SimplifiedType,
- SolverDefId, TraitRef, Ty, TyKind, TypingMode,
+ Binder, ClauseKind, DbInterner, FnSig, GenericArgs, ParamEnv, PredicateKind,
+ SimplifiedType, SolverDefId, TraitRef, Ty, TyKind, TypingMode,
infer::{
BoundRegionConversionTime, DbInternerInferExt, InferCtxt, InferOk,
select::ImplSource,
@@ -47,6 +47,7 @@ use crate::{
obligation_ctxt::ObligationCtxt,
util::clauses_as_obligations,
},
+ traits::ParamEnvAndCrate,
};
pub use self::probe::{
@@ -75,7 +76,7 @@ impl MethodResolutionUnstableFeatures {
pub struct MethodResolutionContext<'a, 'db> {
pub infcx: &'a InferCtxt<'db>,
pub resolver: &'a Resolver<'db>,
- pub env: &'a TraitEnvironment<'db>,
+ pub param_env: ParamEnv<'db>,
pub traits_in_scope: &'a FxHashSet<TraitId>,
pub edition: Edition,
pub unstable_features: &'a MethodResolutionUnstableFeatures,
@@ -194,7 +195,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
let ctx = MethodResolutionContext {
infcx: &self.table.infer_ctxt,
resolver: &self.resolver,
- env: &self.table.trait_env,
+ param_env: self.table.param_env,
traits_in_scope,
edition: self.edition,
unstable_features: &self.unstable_features,
@@ -264,7 +265,7 @@ impl<'db> InferenceTable<'db> {
let obligation = Obligation::new(
self.interner(),
cause,
- self.trait_env.env,
+ self.param_env,
TraitRef::new_from_args(self.interner(), trait_def_id.into(), args),
);
@@ -322,7 +323,7 @@ impl<'db> InferenceTable<'db> {
let bounds = clauses_as_obligations(
bounds.iter_instantiated_copied(interner, args.as_slice()),
ObligationCause::new(),
- self.trait_env.env,
+ self.param_env,
);
obligations.extend(bounds);
@@ -336,7 +337,7 @@ impl<'db> InferenceTable<'db> {
obligations.push(Obligation::new(
interner,
obligation.cause.clone(),
- self.trait_env.env,
+ self.param_env,
Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(ty.into()))),
));
}
@@ -350,7 +351,7 @@ impl<'db> InferenceTable<'db> {
pub fn lookup_impl_const<'db>(
infcx: &InferCtxt<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
const_id: ConstId,
subs: GenericArgs<'db>,
) -> (ConstId, GenericArgs<'db>) {
@@ -380,7 +381,7 @@ pub fn lookup_impl_const<'db>(
/// call the method using the vtable.
pub fn is_dyn_method<'db>(
interner: DbInterner<'db>,
- _env: Arc<TraitEnvironment<'db>>,
+ _env: ParamEnv<'db>,
func: FunctionId,
fn_subst: GenericArgs<'db>,
) -> Option<usize> {
@@ -415,7 +416,7 @@ pub fn is_dyn_method<'db>(
/// Returns `func` if it's not a method defined in a trait or the lookup failed.
pub(crate) fn lookup_impl_method_query<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
func: FunctionId,
fn_subst: GenericArgs<'db>,
) -> (FunctionId, GenericArgs<'db>) {
@@ -433,11 +434,15 @@ pub(crate) fn lookup_impl_method_query<'db>(
);
let name = &db.function_signature(func).name;
- let Some((impl_fn, impl_subst)) =
- lookup_impl_assoc_item_for_trait_ref(&infcx, trait_ref, env, name).and_then(|assoc| {
- if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None }
- })
- else {
+ let Some((impl_fn, impl_subst)) = lookup_impl_assoc_item_for_trait_ref(
+ &infcx,
+ trait_ref,
+ env.param_env,
+ name,
+ )
+ .and_then(|assoc| {
+ if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None }
+ }) else {
return (func, fn_subst);
};
@@ -453,10 +458,10 @@ pub(crate) fn lookup_impl_method_query<'db>(
fn lookup_impl_assoc_item_for_trait_ref<'db>(
infcx: &InferCtxt<'db>,
trait_ref: TraitRef<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
name: &Name,
) -> Option<(AssocItemId, GenericArgs<'db>)> {
- let (impl_id, impl_subst) = find_matching_impl(infcx, &env, trait_ref)?;
+ let (impl_id, impl_subst) = find_matching_impl(infcx, env, trait_ref)?;
let item =
impl_id.impl_items(infcx.interner.db).items.iter().find_map(|(n, it)| match *it {
AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)),
@@ -468,13 +473,12 @@ fn lookup_impl_assoc_item_for_trait_ref<'db>(
pub(crate) fn find_matching_impl<'db>(
infcx: &InferCtxt<'db>,
- env: &TraitEnvironment<'db>,
+ env: ParamEnv<'db>,
trait_ref: TraitRef<'db>,
) -> Option<(ImplId, GenericArgs<'db>)> {
- let trait_ref =
- infcx.at(&ObligationCause::dummy(), env.env).deeply_normalize(trait_ref).ok()?;
+ let trait_ref = infcx.at(&ObligationCause::dummy(), env).deeply_normalize(trait_ref).ok()?;
- let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env.env, trait_ref);
+ let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), env, trait_ref);
let selection = infcx.select(&obligation).ok()??;
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 570dd63a50..6d6515a457 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -507,7 +507,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
GenericPredicates::query_all(self.db(), def_id.into())
.iter_instantiated_copied(self.interner(), all_args),
ObligationCause::new(),
- self.ctx.table.trait_env.env,
+ self.ctx.table.param_env,
);
let sig =
diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs
index adc144ce11..02f86815ed 100644
--- a/crates/hir-ty/src/method_resolution/probe.rs
+++ b/crates/hir-ty/src/method_resolution/probe.rs
@@ -334,7 +334,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
.infcx
.instantiate_query_response_and_region_obligations(
&ObligationCause::new(),
- self.env.env,
+ self.param_env,
&orig_values,
ty,
)
@@ -394,7 +394,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
// converted to, in order to find out which of those methods might actually
// be callable.
let mut autoderef_via_deref =
- Autoderef::new(infcx, self.env, self_ty).include_raw_pointers();
+ Autoderef::new(infcx, self.param_env, self_ty).include_raw_pointers();
let mut reached_raw_pointer = false;
let arbitrary_self_types_enabled = self.unstable_features.arbitrary_self_types
@@ -403,7 +403,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
let reachable_via_deref =
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
- let mut autoderef_via_receiver = Autoderef::new(infcx, self.env, self_ty)
+ let mut autoderef_via_receiver = Autoderef::new(infcx, self.param_env, self_ty)
.include_raw_pointers()
.use_receiver_trait();
let steps = autoderef_via_receiver
@@ -835,7 +835,7 @@ impl<'a, 'db, Choice: ProbeChoice<'db>> ProbeContext<'a, 'db, Choice> {
#[inline]
fn param_env(&self) -> ParamEnv<'db> {
- self.ctx.env.env
+ self.ctx.param_env
}
/// When we're looking up a method by path (UFCS), we relate the receiver
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index f47e3b7a30..3cafb6aa25 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -977,15 +977,13 @@ pub enum Rvalue<'db> {
UnaryOp(UnOp, Operand<'db>),
/// Computes the discriminant of the place, returning it as an integer of type
- /// [`discriminant_ty`]. Returns zero for types without discriminant.
+ /// `discriminant_ty`. Returns zero for types without discriminant.
///
/// The validity requirements for the underlying value are undecided for this rvalue, see
/// [#91095]. Note too that the value of the discriminant is not the same thing as the
- /// variant index; use [`discriminant_for_variant`] to convert.
+ /// variant index; use `discriminant_for_variant` to convert.
///
- /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty
/// [#91095]: https://github.com/rust-lang/rust/issues/91095
- /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant
Discriminant(Place<'db>),
/// Creates an aggregate value, like a tuple or struct.
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 2d2fc03dcc..031654a259 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -12,12 +12,12 @@ use stdx::never;
use triomphe::Arc;
use crate::{
- InferenceResult, TraitEnvironment,
+ InferenceResult,
db::{HirDatabase, InternedClosure, InternedClosureId},
display::DisplayTarget,
mir::OperandKind,
next_solver::{
- DbInterner, GenericArgs, Ty, TypingMode,
+ DbInterner, GenericArgs, ParamEnv, Ty, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
};
@@ -107,8 +107,8 @@ pub fn borrowck_query<'db>(
let infcx = interner.infer_ctxt().build(typing_mode);
res.push(BorrowckResult {
mutability_of_locals: mutability_of_locals(&infcx, &body),
- moved_out_of_ref: moved_out_of_ref(&infcx, &env, &body),
- partially_moved: partially_moved(&infcx, &env, &body),
+ moved_out_of_ref: moved_out_of_ref(&infcx, env, &body),
+ partially_moved: partially_moved(&infcx, env, &body),
borrow_regions: borrow_regions(db, &body),
mir_body: body,
});
@@ -131,7 +131,7 @@ fn make_fetch_closure_field<'db>(
fn moved_out_of_ref<'db>(
infcx: &InferCtxt<'db>,
- env: &TraitEnvironment<'db>,
+ env: ParamEnv<'db>,
body: &MirBody<'db>,
) -> Vec<MovedOutOfRef<'db>> {
let db = infcx.interner.db;
@@ -152,7 +152,7 @@ fn moved_out_of_ref<'db>(
);
}
if is_dereference_of_ref
- && !infcx.type_is_copy_modulo_regions(env.env, ty)
+ && !infcx.type_is_copy_modulo_regions(env, ty)
&& !ty.references_non_lt_error()
{
result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty });
@@ -231,7 +231,7 @@ fn moved_out_of_ref<'db>(
fn partially_moved<'db>(
infcx: &InferCtxt<'db>,
- env: &TraitEnvironment<'db>,
+ env: ParamEnv<'db>,
body: &MirBody<'db>,
) -> Vec<PartiallyMoved<'db>> {
let db = infcx.interner.db;
@@ -247,7 +247,7 @@ fn partially_moved<'db>(
body.owner.module(db).krate(),
);
}
- if !infcx.type_is_copy_modulo_regions(env.env, ty) && !ty.references_non_lt_error() {
+ if !infcx.type_is_copy_modulo_regions(env, ty) && !ty.references_non_lt_error() {
result.push(PartiallyMoved { span, ty, local: p.local });
}
}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 3418689027..02e322f037 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -34,7 +34,7 @@ use syntax::{SyntaxNodePtr, TextRange};
use triomphe::Arc;
use crate::{
- CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, TraitEnvironment,
+ CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, ParamEnvAndCrate,
consteval::{self, ConstEvalError, try_const_usize},
db::{HirDatabase, InternedClosure, InternedClosureId},
display::{ClosureStyle, DisplayTarget, HirDisplay},
@@ -165,7 +165,7 @@ enum MirOrDynIndex<'db> {
pub struct Evaluator<'db> {
db: &'db dyn HirDatabase,
- trait_env: Arc<TraitEnvironment<'db>>,
+ param_env: ParamEnvAndCrate<'db>,
target_data_layout: Arc<TargetDataLayout>,
stack: Vec<u8>,
heap: Vec<u8>,
@@ -594,7 +594,7 @@ pub fn interpret_mir<'db>(
// a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can
// (and probably should) do better here, for example by excluding bindings outside of the target expression.
assert_placeholder_ty_is_unused: bool,
- trait_env: Option<Arc<TraitEnvironment<'db>>>,
+ trait_env: Option<ParamEnvAndCrate<'db>>,
) -> Result<'db, (Result<'db, Const<'db>>, MirOutput)> {
let ty = body.locals[return_slot()].ty;
let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?;
@@ -632,7 +632,7 @@ impl<'db> Evaluator<'db> {
db: &'db dyn HirDatabase,
owner: DefWithBodyId,
assert_placeholder_ty_is_unused: bool,
- trait_env: Option<Arc<TraitEnvironment<'db>>>,
+ trait_env: Option<ParamEnvAndCrate<'db>>,
) -> Result<'db, Evaluator<'db>> {
let module = owner.module(db);
let crate_id = module.krate();
@@ -654,7 +654,10 @@ impl<'db> Evaluator<'db> {
static_locations: Default::default(),
db,
random_state: oorandom::Rand64::new(0),
- trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)),
+ param_env: trait_env.unwrap_or_else(|| ParamEnvAndCrate {
+ param_env: db.trait_environment_for_body(owner),
+ krate: crate_id,
+ }),
crate_id,
stdout: vec![],
stderr: vec![],
@@ -864,7 +867,7 @@ impl<'db> Evaluator<'db> {
}
let r = self
.db
- .layout_of_ty(ty, self.trait_env.clone())
+ .layout_of_ty(ty, self.param_env)
.map_err(|e| MirEvalError::LayoutError(e, ty))?;
self.layout_cache.borrow_mut().insert(ty, r.clone());
Ok(r)
@@ -1927,18 +1930,17 @@ impl<'db> Evaluator<'db> {
let mut id = const_id.0;
let mut subst = subst;
if let hir_def::GeneralConstId::ConstId(c) = id {
- let (c, s) = lookup_impl_const(&self.infcx, self.trait_env.clone(), c, subst);
+ let (c, s) = lookup_impl_const(&self.infcx, self.param_env.param_env, c, subst);
id = hir_def::GeneralConstId::ConstId(c);
subst = s;
}
result_owner = match id {
- GeneralConstId::ConstId(const_id) => self
- .db
- .const_eval(const_id, subst, Some(self.trait_env.clone()))
- .map_err(|e| {
+ GeneralConstId::ConstId(const_id) => {
+ self.db.const_eval(const_id, subst, Some(self.param_env)).map_err(|e| {
let name = id.name(self.db);
MirEvalError::ConstEvalError(name, Box::new(e))
- })?,
+ })?
+ }
GeneralConstId::StaticId(static_id) => {
self.db.const_eval_static(static_id).map_err(|e| {
let name = id.name(self.db);
@@ -2331,7 +2333,7 @@ impl<'db> Evaluator<'db> {
let ty = ocx
.structurally_normalize_ty(
&ObligationCause::dummy(),
- this.trait_env.env,
+ this.param_env.param_env,
ty,
)
.map_err(|_| MirEvalError::NotSupported("couldn't normalize".to_owned()))?;
@@ -2510,7 +2512,7 @@ impl<'db> Evaluator<'db> {
) -> Result<'db, Option<StackFrame<'db>>> {
let mir_body = self
.db
- .monomorphized_mir_body_for_closure(closure, generic_args, self.trait_env.clone())
+ .monomorphized_mir_body_for_closure(closure, generic_args, self.param_env)
.map_err(|it| MirEvalError::MirLowerErrorForClosure(closure, it))?;
let closure_data = if mir_body.locals[mir_body.param_locals[0]].ty.as_reference().is_some()
{
@@ -2606,16 +2608,19 @@ impl<'db> Evaluator<'db> {
}
let (def, generic_args) = pair;
let r = if let Some(self_ty_idx) =
- is_dyn_method(self.interner(), self.trait_env.clone(), def, generic_args)
+ is_dyn_method(self.interner(), self.param_env.param_env, def, generic_args)
{
MirOrDynIndex::Dyn(self_ty_idx)
} else {
- let (imp, generic_args) =
- self.db.lookup_impl_method(self.trait_env.clone(), def, generic_args);
+ let (imp, generic_args) = self.db.lookup_impl_method(
+ ParamEnvAndCrate { param_env: self.param_env.param_env, krate: self.crate_id },
+ def,
+ generic_args,
+ );
let mir_body = self
.db
- .monomorphized_mir_body(imp.into(), generic_args, self.trait_env.clone())
+ .monomorphized_mir_body(imp.into(), generic_args, self.param_env)
.map_err(|e| {
MirEvalError::InFunction(
Box::new(MirEvalError::MirLowerError(imp, e)),
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 591c12ec24..42c11113ee 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -840,7 +840,7 @@ impl<'db> Evaluator<'db> {
"size_of generic arg is not provided".into(),
));
};
- let result = match has_drop_glue(&self.infcx, ty, self.trait_env.clone()) {
+ let result = match has_drop_glue(&self.infcx, ty, self.param_env.param_env) {
DropGlue::HasDropGlue => true,
DropGlue::None => false,
DropGlue::DependOnParams => {
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index bb2afb2f00..2c0c3427cb 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -1,4 +1,4 @@
-use hir_def::db::DefDatabase;
+use hir_def::{HasModule, db::DefDatabase};
use hir_expand::EditionedFileId;
use span::Edition;
use syntax::{TextRange, TextSize};
@@ -40,7 +40,10 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
.monomorphized_mir_body(
func_id.into(),
GenericArgs::new_from_iter(interner, []),
- db.trait_environment(func_id.into()),
+ crate::ParamEnvAndCrate {
+ param_env: db.trait_environment(func_id.into()),
+ krate: func_id.krate(db),
+ },
)
.map_err(|e| MirEvalError::MirLowerError(func_id, e))?;
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 190b2f99cc..5bce4222a4 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -25,7 +25,7 @@ use syntax::TextRange;
use triomphe::Arc;
use crate::{
- Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment,
+ Adjust, Adjustment, AutoBorrow, CallableDefId, ParamEnvAndCrate,
consteval::ConstEvalError,
db::{HirDatabase, InternedClosure, InternedClosureId},
display::{DisplayTarget, HirDisplay, hir_display_with_store},
@@ -42,7 +42,7 @@ use crate::{
TupleFieldId, Ty, UnOp, VariantId, return_slot,
},
next_solver::{
- Const, DbInterner, ParamConst, Region, TyKind, TypingMode, UnevaluatedConst,
+ Const, DbInterner, ParamConst, ParamEnv, Region, TyKind, TypingMode, UnevaluatedConst,
infer::{DbInternerInferExt, InferCtxt},
},
traits::FnTrait,
@@ -81,7 +81,7 @@ struct MirLowerCtx<'a, 'db> {
infer: &'a InferenceResult<'db>,
resolver: Resolver<'db>,
drop_scopes: Vec<DropScope<'db>>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
infcx: InferCtxt<'db>,
}
@@ -302,7 +302,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
};
let resolver = owner.resolver(db);
let env = db.trait_environment_for_body(owner);
- let interner = DbInterner::new_with(db, env.krate);
+ let interner = DbInterner::new_with(db, resolver.krate());
// FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body?
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
@@ -1462,7 +1462,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
}
fn lower_literal_to_operand(&mut self, ty: Ty<'db>, l: &Literal) -> Result<'db, Operand<'db>> {
- let size = || self.db.layout_of_ty(ty, self.env.clone()).map(|it| it.size.bytes_usize());
+ let size = || {
+ self.db
+ .layout_of_ty(ty, ParamEnvAndCrate { param_env: self.env, krate: self.krate() })
+ .map(|it| it.size.bytes_usize())
+ };
const USIZE_SIZE: usize = size_of::<usize>();
let bytes: Box<[_]> = match l {
hir_def::hir::Literal::String(b) => {
@@ -1799,7 +1803,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
&self.infcx,
self.infer[expr_id],
self.owner.module(self.db),
- self.env.clone(),
+ self.env,
)
}
@@ -2070,7 +2074,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
span: MirSpan,
) {
for &l in scope.locals.iter().rev() {
- if !self.infcx.type_is_copy_modulo_regions(self.env.env, self.result.locals[l].ty) {
+ if !self.infcx.type_is_copy_modulo_regions(self.env, self.result.locals[l].ty) {
let prev = std::mem::replace(current, self.new_basic_block());
self.set_terminator(
prev,
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index 1f73d5cd31..b67365c344 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -14,9 +14,11 @@ use rustc_type_ir::{
};
use triomphe::Arc;
-use crate::next_solver::{Const, ConstKind, Region, RegionKind};
use crate::{
- TraitEnvironment,
+ ParamEnvAndCrate,
+ next_solver::{Const, ConstKind, Region, RegionKind},
+};
+use crate::{
db::{HirDatabase, InternedClosureId},
next_solver::{
DbInterner, GenericArgs, Ty, TyKind, TypingMode,
@@ -30,7 +32,7 @@ use super::{MirBody, MirLowerError, Operand, OperandKind, Rvalue, StatementKind,
struct Filler<'db> {
infcx: InferCtxt<'db>,
- trait_env: Arc<TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
subst: GenericArgs<'db>,
}
@@ -53,7 +55,11 @@ impl<'db> FallibleTypeFolder<DbInterner<'db>> for Filler<'db> {
let mut ocx = ObligationCtxt::new(&self.infcx);
let ty = ocx
- .structurally_normalize_ty(&ObligationCause::dummy(), self.trait_env.env, ty)
+ .structurally_normalize_ty(
+ &ObligationCause::dummy(),
+ self.trait_env.param_env,
+ ty,
+ )
.map_err(|_| MirLowerError::NotSupported("can't normalize alias".to_owned()))?;
ty.try_super_fold_with(self)
}
@@ -93,11 +99,7 @@ impl<'db> FallibleTypeFolder<DbInterner<'db>> for Filler<'db> {
}
impl<'db> Filler<'db> {
- fn new(
- db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
- subst: GenericArgs<'db>,
- ) -> Self {
+ fn new(db: &'db dyn HirDatabase, env: ParamEnvAndCrate<'db>, subst: GenericArgs<'db>) -> Self {
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
Self { infcx, trait_env: env, subst }
@@ -210,7 +212,7 @@ pub fn monomorphized_mir_body_query<'db>(
db: &'db dyn HirDatabase,
owner: DefWithBodyId,
subst: GenericArgs<'db>,
- trait_env: Arc<crate::TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> {
let mut filler = Filler::new(db, trait_env, subst);
let body = db.mir_body(owner)?;
@@ -223,7 +225,7 @@ pub(crate) fn monomorphized_mir_body_cycle_result<'db>(
_db: &'db dyn HirDatabase,
_: DefWithBodyId,
_: GenericArgs<'db>,
- _: Arc<crate::TraitEnvironment<'db>>,
+ _: ParamEnvAndCrate<'db>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> {
Err(MirLowerError::Loop)
}
@@ -232,7 +234,7 @@ pub fn monomorphized_mir_body_for_closure_query<'db>(
db: &'db dyn HirDatabase,
closure: InternedClosureId,
subst: GenericArgs<'db>,
- trait_env: Arc<crate::TraitEnvironment<'db>>,
+ trait_env: ParamEnvAndCrate<'db>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>> {
let mut filler = Filler::new(db, trait_env, subst);
let body = db.mir_body_for_closure(closure)?;
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index 443191423a..14b8a61088 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -402,7 +402,7 @@ impl<'db> InferCtxt<'db> {
self.evaluate_obligation(obligation).may_apply()
}
- /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank)
+ /// See the comment on `GeneralAutoderef::overloaded_deref_ty`
/// for more details.
pub fn predicate_may_hold_opaque_types_jank(
&self,
@@ -532,7 +532,7 @@ impl<'db> InferCtxt<'db> {
})
}
- /// See the comment on [OpaqueTypesJank](crate::solve::OpaqueTypesJank)
+ /// See the comment on `GeneralAutoderef::overloaded_deref_ty`
/// for more details.
pub fn goal_may_hold_opaque_types_jank(&self, goal: Goal<'db, Predicate<'db>>) -> bool {
<&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(goal)
diff --git a/crates/hir-ty/src/next_solver/predicate.rs b/crates/hir-ty/src/next_solver/predicate.rs
index 7cc3af748a..783966ee1e 100644
--- a/crates/hir-ty/src/next_solver/predicate.rs
+++ b/crates/hir-ty/src/next_solver/predicate.rs
@@ -427,6 +427,10 @@ impl<'db> ParamEnv<'db> {
pub fn empty() -> Self {
ParamEnv { clauses: Clauses::new_from_iter(DbInterner::conjure(), []) }
}
+
+ pub fn clauses(self) -> Clauses<'db> {
+ self.clauses
+ }
}
impl<'db> rustc_type_ir::inherent::ParamEnv<DbInterner<'db>> for ParamEnv<'db> {
diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs
index 0b84ce13a3..dbac20074b 100644
--- a/crates/hir-ty/src/opaques.rs
+++ b/crates/hir-ty/src/opaques.rs
@@ -122,7 +122,7 @@ pub(crate) fn tait_hidden_types<'db>(
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
let mut ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
- let param_env = db.trait_environment(type_alias.into()).env;
+ let param_env = db.trait_environment(type_alias.into());
let defining_bodies = tait_defining_bodies(db, &loc);
diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs
index 0241751e82..495a9937f6 100644
--- a/crates/hir-ty/src/specialization.rs
+++ b/crates/hir-ty/src/specialization.rs
@@ -1,6 +1,6 @@
//! Impl specialization related things
-use hir_def::{ImplId, nameres::crate_def_map};
+use hir_def::{HasModule, ImplId, nameres::crate_def_map};
use intern::sym;
use rustc_type_ir::inherent::SliceLike;
use tracing::debug;
@@ -46,7 +46,7 @@ fn specializes_query(
parent_impl_def_id: ImplId,
) -> bool {
let trait_env = db.trait_environment(specializing_impl_def_id.into());
- let interner = DbInterner::new_with(db, trait_env.krate);
+ let interner = DbInterner::new_with(db, specializing_impl_def_id.krate(db));
let specializing_impl_signature = db.impl_signature(specializing_impl_def_id);
let parent_impl_signature = db.impl_signature(parent_impl_def_id);
@@ -70,7 +70,7 @@ fn specializes_query(
// create a parameter environment corresponding to an identity instantiation of the specializing impl,
// i.e. the most generic instantiation of the specializing impl.
- let param_env = trait_env.env;
+ let param_env = trait_env;
// Create an infcx, taking the predicates of the specializing impl as assumptions:
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 1462f1e317..b1a2802264 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -4,7 +4,7 @@ use std::hash::Hash;
use base_db::Crate;
use hir_def::{
- AdtId, AssocItemId, BlockId, HasModule, ImplId, Lookup, TraitId,
+ AdtId, AssocItemId, HasModule, ImplId, Lookup, TraitId,
lang_item::LangItems,
nameres::DefMap,
signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
@@ -17,7 +17,6 @@ use rustc_type_ir::{
inherent::{AdtDef, BoundExistentialPredicates, IntoKind, Span as _},
solve::Certainty,
};
-use triomphe::Arc;
use crate::{
db::HirDatabase,
@@ -29,60 +28,22 @@ use crate::{
},
};
-/// A set of clauses that we assume to be true. E.g. if we are inside this function:
-/// ```rust
-/// fn foo<T: Default>(t: T) {}
-/// ```
-/// we assume that `T: Default`.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TraitEnvironment<'db> {
+/// Type for `hir`, because commonly we want both param env and a crate in an exported API.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ParamEnvAndCrate<'db> {
+ pub param_env: ParamEnv<'db>,
pub krate: Crate,
- pub block: Option<BlockId>,
- // FIXME make this a BTreeMap
- traits_from_clauses: Box<[(Ty<'db>, TraitId)]>,
- pub env: ParamEnv<'db>,
-}
-
-impl<'db> TraitEnvironment<'db> {
- pub fn empty(krate: Crate) -> Arc<Self> {
- Arc::new(TraitEnvironment {
- krate,
- block: None,
- traits_from_clauses: Box::default(),
- env: ParamEnv::empty(),
- })
- }
-
- pub fn new(
- krate: Crate,
- block: Option<BlockId>,
- traits_from_clauses: Box<[(Ty<'db>, TraitId)]>,
- env: ParamEnv<'db>,
- ) -> Arc<Self> {
- Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env })
- }
-
- // pub fn with_block(self: &mut Arc<Self>, block: BlockId) {
- pub fn with_block(this: &mut Arc<Self>, block: BlockId) {
- Arc::make_mut(this).block = Some(block);
- }
-
- pub fn traits_in_scope_from_clauses(&self, ty: Ty<'db>) -> impl Iterator<Item = TraitId> + '_ {
- self.traits_from_clauses
- .iter()
- .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id))
- }
}
/// This should be used in `hir` only.
pub fn structurally_normalize_ty<'db>(
infcx: &InferCtxt<'db>,
ty: Ty<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnv<'db>,
) -> Ty<'db> {
let TyKind::Alias(..) = ty.kind() else { return ty };
let mut ocx = ObligationCtxt::new(infcx);
- let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty);
+ let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, ty).unwrap_or(ty);
ty.replace_infer_with_error(infcx.interner)
}
@@ -192,7 +153,7 @@ impl FnTrait {
pub fn implements_trait_unique<'db>(
ty: Ty<'db>,
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
trait_: TraitId,
) -> bool {
implements_trait_unique_impl(db, env, trait_, &mut |infcx| {
@@ -203,7 +164,7 @@ pub fn implements_trait_unique<'db>(
/// This should not be used in `hir-ty`, only in `hir`.
pub fn implements_trait_unique_with_args<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
trait_: TraitId,
args: GenericArgs<'db>,
) -> bool {
@@ -212,7 +173,7 @@ pub fn implements_trait_unique_with_args<'db>(
fn implements_trait_unique_impl<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
trait_: TraitId,
create_args: &mut dyn FnMut(&InferCtxt<'db>) -> GenericArgs<'db>,
) -> bool {
@@ -222,7 +183,7 @@ fn implements_trait_unique_impl<'db>(
let args = create_args(&infcx);
let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args);
- let goal = Goal::new(interner, env.env, trait_ref);
+ let goal = Goal::new(interner, env.param_env, trait_ref);
let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal);
matches!(result, Ok((_, Certainty::Yes)))
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 5e716c6df1..2f412d88ab 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -412,9 +412,7 @@ fn resolve_impl_trait_item<'db>(
ns: Option<Namespace>,
) -> Option<DocLinkDef> {
let krate = ty.krate(db);
- let environment = resolver
- .generic_def()
- .map_or_else(|| crate::TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
+ let environment = crate::param_env_from_resolver(db, &resolver);
let traits_in_scope = resolver.traits_in_scope(db);
// `ty.iterate_path_candidates()` require a scope, which is not available when resolving
@@ -428,7 +426,7 @@ fn resolve_impl_trait_item<'db>(
let ctx = MethodResolutionContext {
infcx: &infcx,
resolver: &resolver,
- env: &environment,
+ param_env: environment.param_env,
traits_in_scope: &traits_in_scope,
edition: krate.edition(db),
unstable_features: &unstable_features,
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 10a1fa12e0..07e61a83c4 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -13,7 +13,7 @@ use hir_ty::{
GenericPredicates,
db::HirDatabase,
display::{
- HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault,
+ HirDisplay, HirDisplayWithExpressionStore, HirFormatter, Result, SizedByDefault,
hir_display_with_store, write_bounds_like_dyn_trait_with_prefix, write_visibility,
},
next_solver::ClauseKind,
@@ -29,7 +29,7 @@ use crate::{
};
impl<'db> HirDisplay<'db> for Function {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let db = f.db;
let data = db.function_signature(self.id);
let container = self.as_assoc_item(db).map(|it| it.container(db));
@@ -185,10 +185,7 @@ impl<'db> HirDisplay<'db> for Function {
}
}
-fn write_impl_header<'db>(
- impl_: &Impl,
- f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+fn write_impl_header<'db>(impl_: &Impl, f: &mut HirFormatter<'_, 'db>) -> Result {
let db = f.db;
f.write_str("impl")?;
@@ -207,7 +204,7 @@ fn write_impl_header<'db>(
}
impl<'db> HirDisplay<'db> for SelfParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let data = f.db.function_signature(self.func);
let param = *data.params.first().unwrap();
match &data.store[param] {
@@ -233,7 +230,7 @@ impl<'db> HirDisplay<'db> for SelfParam {
}
impl<'db> HirDisplay<'db> for Adt {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self {
Adt::Struct(it) => it.hir_fmt(f),
Adt::Union(it) => it.hir_fmt(f),
@@ -243,7 +240,7 @@ impl<'db> HirDisplay<'db> for Adt {
}
impl<'db> HirDisplay<'db> for Struct {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let module_id = self.module(f.db).id;
// FIXME: Render repr if its set explicitly?
write_visibility(module_id, self.visibility(f.db), f)?;
@@ -284,7 +281,7 @@ impl<'db> HirDisplay<'db> for Struct {
}
impl<'db> HirDisplay<'db> for Enum {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("enum ")?;
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
@@ -301,7 +298,7 @@ impl<'db> HirDisplay<'db> for Enum {
}
impl<'db> HirDisplay<'db> for Union {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("union ")?;
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
@@ -322,7 +319,7 @@ fn write_fields<'db>(
limit: usize,
in_line: bool,
f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
let count = fields.len().min(limit);
let (indent, separator) = if in_line { ("", ' ') } else { (" ", '\n') };
f.write_char(if !has_where_clause { ' ' } else { separator })?;
@@ -355,7 +352,7 @@ fn write_variants<'db>(
has_where_clause: bool,
limit: usize,
f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
let count = variants.len().min(limit);
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
if count == 0 {
@@ -391,7 +388,7 @@ fn write_variants<'db>(
}
impl<'db> HirDisplay<'db> for Field {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
write!(f, "{}: ", self.name(f.db).display(f.db, f.edition()))?;
self.ty(f.db).hir_fmt(f)
@@ -399,14 +396,14 @@ impl<'db> HirDisplay<'db> for Field {
}
impl<'db> HirDisplay<'db> for TupleField {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write!(f, "pub {}: ", self.name().display(f.db, f.edition()))?;
self.ty(f.db).hir_fmt(f)
}
}
impl<'db> HirDisplay<'db> for Variant {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
let data = self.id.fields(f.db);
match data.shape {
@@ -436,19 +433,19 @@ impl<'db> HirDisplay<'db> for Variant {
}
impl<'db> HirDisplay<'db> for Type<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
self.ty.hir_fmt(f)
}
}
impl<'db> HirDisplay<'db> for TypeNs<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
self.ty.hir_fmt(f)
}
}
impl<'db> HirDisplay<'db> for ExternCrateDecl {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("extern crate ")?;
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
@@ -460,7 +457,7 @@ impl<'db> HirDisplay<'db> for ExternCrateDecl {
}
impl<'db> HirDisplay<'db> for GenericParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self {
GenericParam::TypeParam(it) => it.hir_fmt(f),
GenericParam::ConstParam(it) => it.hir_fmt(f),
@@ -470,7 +467,7 @@ impl<'db> HirDisplay<'db> for GenericParam {
}
impl<'db> HirDisplay<'db> for TypeOrConstParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.split(f.db) {
either::Either::Left(it) => it.hir_fmt(f),
either::Either::Right(it) => it.hir_fmt(f),
@@ -479,7 +476,7 @@ impl<'db> HirDisplay<'db> for TypeOrConstParam {
}
impl<'db> HirDisplay<'db> for TypeParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let params = f.db.generic_params(self.id.parent());
let param_data = &params[self.id.local_id()];
let krate = self.id.parent().krate(f.db).id;
@@ -541,22 +538,19 @@ impl<'db> HirDisplay<'db> for TypeParam {
}
impl<'db> HirDisplay<'db> for LifetimeParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))
}
}
impl<'db> HirDisplay<'db> for ConstParam {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write!(f, "const {}: ", self.name(f.db).display(f.db, f.edition()))?;
self.ty(f.db).hir_fmt(f)
}
}
-fn write_generic_params<'db>(
- def: GenericDefId,
- f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+fn write_generic_params<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result {
let (params, store) = f.db.generic_params_and_store(def);
if params.iter_lt().next().is_none()
&& params.iter_type_or_consts().all(|it| it.1.const_param().is_none())
@@ -614,10 +608,7 @@ fn write_generic_params<'db>(
Ok(())
}
-fn write_where_clause<'db>(
- def: GenericDefId,
- f: &mut HirFormatter<'_, 'db>,
-) -> Result<bool, HirDisplayError> {
+fn write_where_clause<'db>(def: GenericDefId, f: &mut HirFormatter<'_, 'db>) -> Result<bool> {
let (params, store) = f.db.generic_params_and_store(def);
if !has_disaplayable_predicates(f.db, &params, &store) {
return Ok(false);
@@ -649,7 +640,7 @@ fn write_where_predicates<'db>(
params: &GenericParams,
store: &ExpressionStore,
f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+) -> Result {
use WherePredicate::*;
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
@@ -710,7 +701,7 @@ fn write_where_predicates<'db>(
}
impl<'db> HirDisplay<'db> for Const {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
let db = f.db;
let container = self.as_assoc_item(db).map(|it| it.container(db));
let mut module = self.module(db);
@@ -731,7 +722,7 @@ impl<'db> HirDisplay<'db> for Const {
}
impl<'db> HirDisplay<'db> for Static {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.static_signature(self.id);
f.write_str("static ")?;
@@ -745,13 +736,13 @@ impl<'db> HirDisplay<'db> for Static {
}
impl<'db> HirDisplay<'db> for TraitRef<'db> {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
self.trait_ref.hir_fmt(f)
}
}
impl<'db> HirDisplay<'db> for Trait {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
// FIXME(trait-alias) needs special handling to print the equal sign
write_trait_header(self, f)?;
let def_id = GenericDefId::TraitId(self.id);
@@ -790,10 +781,7 @@ impl<'db> HirDisplay<'db> for Trait {
}
}
-fn write_trait_header<'db>(
- trait_: &Trait,
- f: &mut HirFormatter<'_, 'db>,
-) -> Result<(), HirDisplayError> {
+fn write_trait_header<'db>(trait_: &Trait, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
let data = f.db.trait_signature(trait_.id);
if data.flags.contains(TraitFlags::UNSAFE) {
@@ -808,7 +796,7 @@ fn write_trait_header<'db>(
}
impl<'db> HirDisplay<'db> for TypeAlias {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.type_alias_signature(self.id);
write!(f, "type {}", data.name.display(f.db, f.edition()))?;
@@ -831,7 +819,7 @@ impl<'db> HirDisplay<'db> for TypeAlias {
}
impl<'db> HirDisplay<'db> for Module {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.parent(f.db) {
Some(m) => write_visibility(m.id, self.visibility(f.db), f)?,
None => {
@@ -849,7 +837,7 @@ impl<'db> HirDisplay<'db> for Module {
}
impl<'db> HirDisplay<'db> for Crate {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.display_name(f.db) {
Some(name) => write!(f, "extern crate {name}"),
None => f.write_str("extern crate {unknown}"),
@@ -858,7 +846,7 @@ impl<'db> HirDisplay<'db> for Crate {
}
impl<'db> HirDisplay<'db> for Macro {
- fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.id {
hir_def::MacroId::Macro2Id(_) => f.write_str("macro"),
hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index 6f427d728b..9ea1456a41 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -20,7 +20,7 @@ use crate::{
pub trait HasSource {
type Ast;
/// Fetches the definition's source node.
- /// Using [`crate::Semantics::source`] is preferred when working with [`crate::Semantics`],
+ /// Using [`crate::SemanticsImpl::source`] is preferred when working with [`crate::Semantics`],
/// as that caches the parsed file in the semantics' cache.
///
/// The current some implementations can return `InFile` instead of `Option<InFile>`.
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 2146e4db77..2210bb79cd 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -76,7 +76,7 @@ use hir_expand::{
AstId, MacroCallKind, RenderedExpandError, ValueResult, proc_macro::ProcMacroKind,
};
use hir_ty::{
- GenericPredicates, InferenceResult, TraitEnvironment, TyDefId, TyLoweringDiagnostic,
+ GenericPredicates, InferenceResult, ParamEnvAndCrate, TyDefId, TyLoweringDiagnostic,
ValueTyDefId, all_super_traits, autoderef, check_orphan_rules,
consteval::try_const_usize,
db::{InternedClosureId, InternedCoroutineId},
@@ -89,7 +89,7 @@ use hir_ty::{
mir::{MutBorrowKind, interpret_mir},
next_solver::{
AliasTy, ClauseKind, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
- PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
+ ParamEnv, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
traits::{self, is_inherent_impl_coherent, structurally_normalize_ty},
@@ -1245,7 +1245,7 @@ impl TupleField {
.get(self.index as usize)
.copied()
.unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed));
- Type { env: db.trait_environment_for_body(self.owner), ty }
+ Type { env: body_param_env_from_has_crate(db, self.owner), ty }
}
}
@@ -1322,13 +1322,16 @@ impl Field {
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
db.layout_of_ty(
self.ty(db).ty,
- db.trait_environment(match hir_def::VariantId::from(self.parent) {
- hir_def::VariantId::EnumVariantId(id) => {
- GenericDefId::AdtId(id.lookup(db).parent.into())
- }
- hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
- hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
- }),
+ param_env_from_has_crate(
+ db,
+ match hir_def::VariantId::from(self.parent) {
+ hir_def::VariantId::EnumVariantId(id) => {
+ GenericDefId::AdtId(id.lookup(db).parent.into())
+ }
+ hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
+ hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
+ },
+ ),
)
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
}
@@ -1745,13 +1748,12 @@ impl Adt {
}
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
- let env = db.trait_environment(self.into());
let interner = DbInterner::new_no_crate(db);
let adt_id = AdtId::from(self);
let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| {
GenericArg::error_from_id(interner, id)
});
- db.layout_of_adt(adt_id, args, env)
+ db.layout_of_adt(adt_id, args, param_env_from_has_crate(db, adt_id))
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
}
@@ -2276,7 +2278,7 @@ impl Function {
}
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
- let environment = db.trait_environment(self.id.into());
+ let environment = param_env_from_has_crate(db, self.id);
// FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let callable_sig =
db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder();
@@ -2285,7 +2287,7 @@ impl Function {
.iter()
.enumerate()
.map(|(idx, ty)| {
- let ty = Type { env: environment.clone(), ty };
+ let ty = Type { env: environment, ty };
Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
@@ -2301,7 +2303,7 @@ impl Function {
}
pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
- let environment = db.trait_environment(self.id.into());
+ let environment = param_env_from_has_crate(db, self.id);
// FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let callable_sig =
db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder();
@@ -2312,7 +2314,7 @@ impl Function {
.enumerate()
.skip(skip)
.map(|(idx, ty)| {
- let ty = Type { env: environment.clone(), ty };
+ let ty = Type { env: environment, ty };
Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
@@ -2324,7 +2326,7 @@ impl Function {
db: &'db dyn HirDatabase,
generics: impl Iterator<Item = Type<'db>>,
) -> Vec<Param<'db>> {
- let environment = db.trait_environment(self.id.into());
+ let environment = param_env_from_has_crate(db, self.id);
let interner = DbInterner::new_no_crate(db);
let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty));
let callable_sig =
@@ -2336,7 +2338,7 @@ impl Function {
.enumerate()
.skip(skip)
.map(|(idx, ty)| {
- let ty = Type { env: environment.clone(), ty };
+ let ty = Type { env: environment, ty };
Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
@@ -2471,7 +2473,10 @@ impl Function {
let body = db.monomorphized_mir_body(
self.id.into(),
GenericArgs::new_from_iter(interner, []),
- db.trait_environment(self.id.into()),
+ ParamEnvAndCrate {
+ param_env: db.trait_environment(self.id.into()),
+ krate: self.id.module(db).krate(),
+ },
)?;
let (result, output) = interpret_mir(db, body, false, None)?;
let mut text = match result {
@@ -2613,7 +2618,7 @@ impl SelfParam {
// FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
let callable_sig =
db.callable_item_signature(self.func.into()).instantiate_identity().skip_binder();
- let environment = db.trait_environment(self.func.into());
+ let environment = param_env_from_has_crate(db, self.func);
let ty = callable_sig.inputs().as_slice()[0];
Type { env: environment, ty }
}
@@ -2628,7 +2633,7 @@ impl SelfParam {
let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty));
let callable_sig =
db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder();
- let environment = db.trait_environment(self.func.into());
+ let environment = param_env_from_has_crate(db, self.func);
let ty = callable_sig.inputs().as_slice()[0];
Type { env: environment, ty }
}
@@ -3687,11 +3692,11 @@ impl GenericDef {
pub struct GenericSubstitution<'db> {
def: GenericDefId,
subst: GenericArgs<'db>,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
}
impl<'db> GenericSubstitution<'db> {
- fn new(def: GenericDefId, subst: GenericArgs<'db>, env: Arc<TraitEnvironment<'db>>) -> Self {
+ fn new(def: GenericDefId, subst: GenericArgs<'db>, env: ParamEnvAndCrate<'db>) -> Self {
Self { def, subst, env }
}
@@ -3737,9 +3742,7 @@ impl<'db> GenericSubstitution<'db> {
.zip(type_params);
container_params
.chain(self_params)
- .filter_map(|(ty, name)| {
- Some((name?.symbol().clone(), Type { ty, env: self.env.clone() }))
- })
+ .filter_map(|(ty, name)| Some((name?.symbol().clone(), Type { ty, env: self.env })))
.collect()
}
}
@@ -4459,7 +4462,7 @@ impl Impl {
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TraitRef<'db> {
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
trait_ref: hir_ty::next_solver::TraitRef<'db>,
}
@@ -4469,9 +4472,7 @@ impl<'db> TraitRef<'db> {
resolver: &Resolver<'_>,
trait_ref: hir_ty::next_solver::TraitRef<'db>,
) -> Self {
- let env = resolver
- .generic_def()
- .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
+ let env = param_env_from_resolver(db, resolver);
TraitRef { env, trait_ref }
}
@@ -4481,7 +4482,7 @@ impl<'db> TraitRef<'db> {
pub fn self_ty(&self) -> TypeNs<'_> {
let ty = self.trait_ref.self_ty();
- TypeNs { env: self.env.clone(), ty }
+ TypeNs { env: self.env, ty }
}
/// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
@@ -4492,7 +4493,7 @@ impl<'db> TraitRef<'db> {
.as_slice()
.get(idx)
.and_then(|arg| arg.ty())
- .map(|ty| TypeNs { env: self.env.clone(), ty })
+ .map(|ty| TypeNs { env: self.env, ty })
}
}
@@ -4556,11 +4557,8 @@ impl<'db> Closure<'db> {
let owner = db.lookup_intern_closure(id).0;
let infer = InferenceResult::for_body(db, owner);
let (captures, _) = infer.closure_info(id);
- let env = db.trait_environment_for_body(owner);
- captures
- .iter()
- .map(|capture| Type { env: env.clone(), ty: capture.ty(db, self.subst) })
- .collect()
+ let env = body_param_env_from_has_crate(db, owner);
+ captures.iter().map(|capture| Type { env, ty: capture.ty(db, self.subst) }).collect()
}
pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
@@ -4768,7 +4766,7 @@ impl CaptureUsageSource {
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Type<'db> {
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
ty: Ty<'db>,
}
@@ -4786,21 +4784,17 @@ impl<'db> Type<'db> {
resolver: &Resolver<'_>,
ty: Ty<'db>,
) -> Self {
- let environment = resolver
- .generic_def()
- .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
+ let environment = param_env_from_resolver(db, resolver);
Type { env: environment, ty }
}
pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty<'db>) -> Self {
- Type { env: TraitEnvironment::empty(krate), ty }
+ Type { env: empty_param_env(krate), ty }
}
fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
let resolver = lexical_env.resolver(db);
- let environment = resolver
- .generic_def()
- .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
+ let environment = param_env_from_resolver(db, &resolver);
Type { env: environment, ty }
}
@@ -4856,7 +4850,7 @@ impl<'db> Type<'db> {
pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self {
let tys = tys.iter().map(|it| it.ty);
let interner = DbInterner::conjure();
- Type { env: TraitEnvironment::empty(krate), ty: Ty::new_tup_from_iter(interner, tys) }
+ Type { env: empty_param_env(krate), ty: Ty::new_tup_from_iter(interner, tys) }
}
pub fn is_unit(&self) -> bool {
@@ -5046,7 +5040,7 @@ impl<'db> Type<'db> {
})
.or(lang_items.Future)?;
- if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
+ if !traits::implements_trait_unique(self.ty, db, self.env, trait_) {
return None;
}
@@ -5077,7 +5071,7 @@ impl<'db> Type<'db> {
let Some(iterator_trait) = lang_items.Iterator else {
return false;
};
- traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait)
+ traits::implements_trait_unique(self.ty, db, self.env, iterator_trait)
}
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
@@ -5089,7 +5083,7 @@ impl<'db> Type<'db> {
Some(into_iter_trait.id)
})?;
- if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
+ if !traits::implements_trait_unique(self.ty, db, self.env, trait_) {
return None;
}
@@ -5110,7 +5104,7 @@ impl<'db> Type<'db> {
None => return false,
};
- traits::implements_trait_unique(self.ty, db, self.env.clone(), fnonce_trait)
+ traits::implements_trait_unique(self.ty, db, self.env, fnonce_trait)
}
// FIXME: Find better API that also handles const generics
@@ -5121,7 +5115,7 @@ impl<'db> Type<'db> {
trait_.id.into(),
std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)),
);
- traits::implements_trait_unique_with_args(db, self.env.clone(), trait_.id, args)
+ traits::implements_trait_unique_with_args(db, self.env, trait_.id, args)
}
pub fn normalize_trait_assoc_type(
@@ -5144,7 +5138,7 @@ impl<'db> Type<'db> {
);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let ty = structurally_normalize_ty(&infcx, projection, self.env.clone());
+ let ty = structurally_normalize_ty(&infcx, projection, self.env.param_env);
if ty.is_ty_error() { None } else { Some(self.derived(ty)) }
}
@@ -5166,8 +5160,7 @@ impl<'db> Type<'db> {
// This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
_ => {
- let (fn_trait, sig) =
- hir_ty::callable_sig_from_fn_trait(self.ty, self.env.clone(), db)?;
+ let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(self.ty, self.env, db)?;
return Some(Callable {
ty: self.clone(),
sig,
@@ -5291,7 +5284,7 @@ impl<'db> Type<'db> {
let interner = DbInterner::new_no_crate(db);
// There should be no inference vars in types passed here
let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty);
- autoderef(db, self.env.clone(), canonical)
+ autoderef(db, self.env, canonical)
}
// This would be nicer if it just returned an iterator, but that runs into
@@ -5477,13 +5470,11 @@ impl<'db> Type<'db> {
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let unstable_features =
MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map());
- let environment = resolver
- .generic_def()
- .map_or_else(|| TraitEnvironment::empty(module.krate()), |d| db.trait_environment(d));
+ let environment = param_env_from_resolver(db, resolver);
let ctx = MethodResolutionContext {
infcx: &infcx,
resolver,
- env: &environment,
+ param_env: environment.param_env,
traits_in_scope,
edition: resolver.krate().data(db).edition,
unstable_features: &unstable_features,
@@ -5704,7 +5695,13 @@ impl<'db> Type<'db> {
.filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
.flat_map(|ty| {
self.env
- .traits_in_scope_from_clauses(ty)
+ .param_env
+ .clauses()
+ .iter()
+ .filter_map(move |pred| match pred.kind().skip_binder() {
+ ClauseKind::Trait(tr) if tr.self_ty() == ty => Some(tr.def_id().0),
+ _ => None,
+ })
.flat_map(|t| hir_ty::all_super_traits(db, t))
})
.map(Trait::from)
@@ -5728,7 +5725,7 @@ impl<'db> Type<'db> {
}
fn derived(&self, ty: Ty<'db>) -> Self {
- Type { env: self.env.clone(), ty }
+ Type { env: self.env, ty }
}
/// Visits every type, including generic arguments, in this type. `callback` is called with type
@@ -5736,7 +5733,7 @@ impl<'db> Type<'db> {
pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
struct Visitor<'db, F> {
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
callback: F,
visited: FxHashSet<Ty<'db>>,
}
@@ -5751,7 +5748,7 @@ impl<'db> Type<'db> {
return;
}
- (self.callback)(Type { env: self.env.clone(), ty });
+ (self.callback)(Type { env: self.env, ty });
if let Some(bounds) = ty.impl_trait_bounds(self.db) {
bounds.visit_with(self);
@@ -5761,8 +5758,7 @@ impl<'db> Type<'db> {
}
}
- let mut visitor =
- Visitor { db, env: self.env.clone(), callback, visited: FxHashSet::default() };
+ let mut visitor = Visitor { db, env: self.env, callback, visited: FxHashSet::default() };
self.ty.visit_with(&mut visitor);
}
/// Check if type unifies with another type.
@@ -5772,7 +5768,7 @@ impl<'db> Type<'db> {
pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
let interner = DbInterner::new_no_crate(db);
let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
- hir_ty::could_unify(db, self.env.clone(), &tys)
+ hir_ty::could_unify(db, self.env, &tys)
}
/// Check if type unifies with another type eagerly making sure there are no unresolved goals.
@@ -5782,13 +5778,13 @@ impl<'db> Type<'db> {
pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
let interner = DbInterner::new_no_crate(db);
let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
- hir_ty::could_unify_deeply(db, self.env.clone(), &tys)
+ hir_ty::could_unify_deeply(db, self.env, &tys)
}
pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
let interner = DbInterner::new_no_crate(db);
let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty));
- hir_ty::could_coerce(db, self.env.clone(), &tys)
+ hir_ty::could_coerce(db, self.env, &tys)
}
pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
@@ -5807,34 +5803,32 @@ impl<'db> Type<'db> {
}
pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> {
- db.layout_of_ty(self.ty, self.env.clone())
+ db.layout_of_ty(self.ty, self.env)
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
}
pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
let interner = DbInterner::new_with(db, self.env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone())
+ hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.param_env)
}
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeNs<'db> {
- env: Arc<TraitEnvironment<'db>>,
+ env: ParamEnvAndCrate<'db>,
ty: Ty<'db>,
}
impl<'db> TypeNs<'db> {
fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
let resolver = lexical_env.resolver(db);
- let environment = resolver
- .generic_def()
- .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
+ let environment = param_env_from_resolver(db, &resolver);
TypeNs { env: environment, ty }
}
pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> {
- Type { env: self.env.clone(), ty: self.ty }
+ Type { env: self.env, ty: self.ty }
}
// FIXME: Find better API that also handles const generics
@@ -6546,5 +6540,35 @@ fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId)
})
}
+fn param_env_from_resolver<'db>(
+ db: &'db dyn HirDatabase,
+ resolver: &Resolver<'_>,
+) -> ParamEnvAndCrate<'db> {
+ ParamEnvAndCrate {
+ param_env: resolver
+ .generic_def()
+ .map_or_else(ParamEnv::empty, |generic_def| db.trait_environment(generic_def)),
+ krate: resolver.krate(),
+ }
+}
+
+fn param_env_from_has_crate<'db>(
+ db: &'db dyn HirDatabase,
+ id: impl hir_def::HasModule + Into<GenericDefId> + Copy,
+) -> ParamEnvAndCrate<'db> {
+ ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.krate(db) }
+}
+
+fn body_param_env_from_has_crate<'db>(
+ db: &'db dyn HirDatabase,
+ id: impl hir_def::HasModule + Into<DefWithBodyId> + Copy,
+) -> ParamEnvAndCrate<'db> {
+ ParamEnvAndCrate { param_env: db.trait_environment_for_body(id.into()), krate: id.krate(db) }
+}
+
+fn empty_param_env<'db>(krate: base_db::Crate) -> ParamEnvAndCrate<'db> {
+ ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }
+}
+
pub use hir_ty::next_solver;
pub use hir_ty::setup_tracing;
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 8144b2f737..901c9e1575 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -29,7 +29,7 @@ use hir_expand::{
name::{AsName, Name},
};
use hir_ty::{
- Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext,
+ Adjustment, InferenceResult, LifetimeElisionKind, ParamEnvAndCrate, TyLoweringContext,
diagnostics::{
InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields,
unsafe_operations,
@@ -37,7 +37,8 @@ use hir_ty::{
lang_items::lang_items_for_bin_op,
method_resolution::{self, CandidateId},
next_solver::{
- DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt,
+ DbInterner, ErrorGuaranteed, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
+ infer::DbInternerInferExt,
},
traits::structurally_normalize_ty,
};
@@ -227,10 +228,15 @@ impl<'db> SourceAnalyzer<'db> {
})
}
- fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment<'db>> {
- self.body_().map(|(def, ..)| def).map_or_else(
- || TraitEnvironment::empty(self.resolver.krate()),
- |def| db.trait_environment_for_body(def),
+ fn param_and<'a>(&self, param_env: ParamEnv<'a>) -> ParamEnvAndCrate<'a> {
+ ParamEnvAndCrate { param_env, krate: self.resolver.krate() }
+ }
+
+ fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> {
+ self.param_and(
+ self.body_()
+ .map(|(def, ..)| def)
+ .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)),
)
}
@@ -827,7 +833,7 @@ impl<'db> SourceAnalyzer<'db> {
let mut container = Either::Right(container.ty);
for field_name in offset_of_expr.fields() {
if let Either::Right(container) = &mut container {
- *container = structurally_normalize_ty(&infcx, *container, trait_env.clone());
+ *container = structurally_normalize_ty(&infcx, *container, trait_env.param_env);
}
let handle_variants =
|variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {
@@ -1412,7 +1418,7 @@ impl<'db> SourceAnalyzer<'db> {
Some(it) => it,
None => return (func, substs),
};
- let env = db.trait_environment_for_body(owner);
+ let env = self.param_and(db.trait_environment_for_body(owner));
db.lookup_impl_method(env, func, substs)
}
@@ -1426,10 +1432,10 @@ impl<'db> SourceAnalyzer<'db> {
Some(it) => it,
None => return (const_id, subs),
};
- let env = db.trait_environment_for_body(owner);
+ let env = self.param_and(db.trait_environment_for_body(owner));
let interner = DbInterner::new_with(db, env.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- method_resolution::lookup_impl_const(&infcx, env, const_id, subs)
+ method_resolution::lookup_impl_const(&infcx, env.param_env, const_id, subs)
}
fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 0b5dae6bc4..16b5684c16 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -59,6 +59,8 @@
//! <https://rust-analyzer.github.io/blog/2020/09/28/how-to-make-a-light-bulb.html>
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
+// It's useful to refer to code that is private in doc comments.
+#![allow(rustdoc::private_intra_doc_links)]
mod assist_config;
mod assist_context;
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index eab2b9063f..fbb3cde968 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -344,6 +344,60 @@ fn main() {
}
"#,
);
+
+ check_edit(
+ "loop",
+ r#"
+fn main() {
+ let x = &$0
+ bar();
+}
+"#,
+ r#"
+fn main() {
+ let x = &loop {
+ $0
+};
+ bar();
+}
+"#,
+ );
+
+ check_edit(
+ "loop",
+ r#"
+fn main() {
+ let x = -$0
+ bar();
+}
+"#,
+ r#"
+fn main() {
+ let x = -loop {
+ $0
+};
+ bar();
+}
+"#,
+ );
+
+ check_edit(
+ "loop",
+ r#"
+fn main() {
+ let x = 2 + $0
+ bar();
+}
+"#,
+ r#"
+fn main() {
+ let x = 2 + loop {
+ $0
+};
+ bar();
+}
+"#,
+ );
}
#[test]
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index e761da7152..add637a16f 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1321,9 +1321,8 @@ fn classify_name_ref<'db>(
let incomplete_expr_stmt =
it.parent().and_then(ast::ExprStmt::cast).map(|it| it.semicolon_token().is_none());
let before_else_kw = before_else_kw(it);
- let incomplete_let = it
- .parent()
- .and_then(ast::LetStmt::cast)
+ let incomplete_let = left_ancestors(it.parent())
+ .find_map(ast::LetStmt::cast)
.is_some_and(|it| it.semicolon_token().is_none())
|| after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw;
let in_value = is_in_value(it);
@@ -1882,6 +1881,13 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
Some((use_tree.path()?, true))
}
+fn left_ancestors(node: Option<SyntaxNode>) -> impl Iterator<Item = SyntaxNode> {
+ node.into_iter().flat_map(|node| {
+ let end = node.text_range().end();
+ node.ancestors().take_while(move |it| it.text_range().end() == end)
+ })
+}
+
fn is_in_token_of_for_loop(path: &ast::Path) -> bool {
// oh my ...
(|| {
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index c526c7f070..71d32da747 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -23,7 +23,7 @@ use crate::{
/// editor pop-up.
///
/// It is basically a POD with various properties. To construct a [`CompletionItem`],
-/// use [`Builder::new`] method and the [`Builder`] struct.
+/// use the [`Builder`] struct.
#[derive(Clone, UpmapFromRaFixture)]
#[non_exhaustive]
pub struct CompletionItem {
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index f7a118db50..6dfa183136 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -1,5 +1,8 @@
//! `completions` crate provides utilities for generating completions of user input.
+// It's useful to refer to code that is private in doc comments.
+#![allow(rustdoc::private_intra_doc_links)]
+
mod completions;
mod config;
mod context;
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 3dd2c1f6c4..b15bf0cd01 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -3,9 +3,10 @@
//! NOTE: The crate is undergoing refactors, don't believe everything the docs
//! say :-)
//!
-//! The parser doesn't know about concrete representation of tokens and syntax
-//! trees. Abstract [`TokenSource`] and [`TreeSink`] traits are used instead. As
-//! a consequence, this crate does not contain a lexer.
+//! The parser doesn't know about concrete representation of tokens
+//! and syntax trees. Abstract [`Input`] and [`Output`] traits are
+//! used to provide tokens instead. As a consequence, this crate does
+//! not contain a lexer.
//!
//! The [`Parser`] struct from the [`parser`] module is a cursor into the
//! sequence of tokens. Parsing routines use [`Parser`] to inspect current
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index 2c6a82bf0c..d6d9ed4676 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -1,5 +1,5 @@
-//! Thin wrappers around [`camino::path`], distinguishing between absolute and
-//! relative paths.
+//! Thin wrappers around [`camino::Utf8PathBuf`], distinguishing
+//! between absolute and relative paths.
use std::{
borrow::Borrow,
diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs
index 680372210a..a6e228d977 100644
--- a/crates/proc-macro-api/src/legacy_protocol/msg.rs
+++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs
@@ -17,19 +17,19 @@ pub enum Request {
// As such, this is the only request that needs to be supported across all protocol versions
// and by keeping it first, we ensure it always has the same discriminant encoding in postcard
/// Performs an API version check between the client and the server.
- /// Since [`VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::VERSION_CHECK_VERSION`]
ApiVersionCheck {},
/// Retrieves a list of macros from a given dynamic library.
- /// Since [`NO_VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::NO_VERSION_CHECK_VERSION`]
ListMacros { dylib_path: Utf8PathBuf },
/// Expands a procedural macro.
- /// Since [`NO_VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::NO_VERSION_CHECK_VERSION`]
ExpandMacro(Box<ExpandMacro>),
/// Sets server-specific configurations.
- /// Since [`RUST_ANALYZER_SPAN_SUPPORT`]
+ /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`]
SetConfig(ServerConfig),
}
@@ -51,23 +51,23 @@ pub enum Response {
// As such, this is the only request that needs to be supported across all protocol versions
// and by keeping it first, we ensure it always has the same discriminant encoding in postcard
/// Returns the API version supported by the server.
- /// Since [`NO_VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::NO_VERSION_CHECK_VERSION`]
ApiVersionCheck(u32),
/// Returns a list of available macros in a dynamic library.
- /// Since [`NO_VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::NO_VERSION_CHECK_VERSION`]
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
/// Returns result of a macro expansion.
- /// Since [`NO_VERSION_CHECK_VERSION`]
+ /// Since [`crate::version::NO_VERSION_CHECK_VERSION`]
ExpandMacro(Result<FlatTree, PanicMessage>),
/// Confirms the application of a configuration update.
- /// Since [`RUST_ANALYZER_SPAN_SUPPORT`]
+ /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`]
SetConfig(ServerConfig),
/// Returns the result of a macro expansion, including extended span data.
- /// Since [`RUST_ANALYZER_SPAN_SUPPORT`]
+ /// Since [`crate::version::RUST_ANALYZER_SPAN_SUPPORT`]
ExpandMacroExtended(Result<ExpandMacroExtended, PanicMessage>),
}
@@ -185,7 +185,7 @@ mod tests {
use super::*;
- fn fixture_token_tree() -> TopSubtree<Span> {
+ fn fixture_token_tree_top_many_none() -> TopSubtree<Span> {
let anchor = SpanAnchor {
file_id: span::EditionedFileId::new(
span::FileId::from_raw(0xe4e4e),
@@ -201,7 +201,7 @@ mod tests {
ctx: SyntaxContext::root(Edition::CURRENT),
},
close: Span {
- range: TextRange::empty(TextSize::new(19)),
+ range: TextRange::empty(TextSize::new(0)),
anchor,
ctx: SyntaxContext::root(Edition::CURRENT),
},
@@ -259,10 +259,18 @@ mod tests {
ctx: SyntaxContext::root(Edition::CURRENT),
},
);
+ builder.open(
+ DelimiterKind::Bracket,
+ Span {
+ range: TextRange::at(TextSize::new(15), TextSize::of('[')),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ },
+ );
builder.push(Leaf::Literal(Literal {
symbol: sym::INTEGER_0,
span: Span {
- range: TextRange::at(TextSize::new(15), TextSize::of("0u32")),
+ range: TextRange::at(TextSize::new(16), TextSize::of("0u32")),
anchor,
ctx: SyntaxContext::root(Edition::CURRENT),
},
@@ -270,45 +278,140 @@ mod tests {
suffix: Some(sym::u32),
}));
builder.close(Span {
- range: TextRange::at(TextSize::new(19), TextSize::of('}')),
+ range: TextRange::at(TextSize::new(20), TextSize::of(']')),
anchor,
ctx: SyntaxContext::root(Edition::CURRENT),
});
+ builder.close(Span {
+ range: TextRange::at(TextSize::new(21), TextSize::of('}')),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ });
+
+ builder.build()
+ }
+
+ fn fixture_token_tree_top_empty_none() -> TopSubtree<Span> {
+ let anchor = SpanAnchor {
+ file_id: span::EditionedFileId::new(
+ span::FileId::from_raw(0xe4e4e),
+ span::Edition::CURRENT,
+ ),
+ ast_id: ROOT_ERASED_FILE_AST_ID,
+ };
+
+ let builder = TopSubtreeBuilder::new(Delimiter {
+ open: Span {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ },
+ close: Span {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ },
+ kind: DelimiterKind::Invisible,
+ });
+
+ builder.build()
+ }
+
+ fn fixture_token_tree_top_empty_brace() -> TopSubtree<Span> {
+ let anchor = SpanAnchor {
+ file_id: span::EditionedFileId::new(
+ span::FileId::from_raw(0xe4e4e),
+ span::Edition::CURRENT,
+ ),
+ ast_id: ROOT_ERASED_FILE_AST_ID,
+ };
+
+ let builder = TopSubtreeBuilder::new(Delimiter {
+ open: Span {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ },
+ close: Span {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor,
+ ctx: SyntaxContext::root(Edition::CURRENT),
+ },
+ kind: DelimiterKind::Brace,
+ });
+
builder.build()
}
#[test]
fn test_proc_macro_rpc_works() {
- let tt = fixture_token_tree();
- for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION {
- let mut span_data_table = Default::default();
- let task = ExpandMacro {
- data: ExpandMacroData {
- macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table),
- macro_name: Default::default(),
- attributes: None,
- has_global_spans: ExpnGlobals {
- serialize: true,
- def_site: 0,
- call_site: 0,
- mixed_site: 0,
+ for tt in [
+ fixture_token_tree_top_many_none,
+ fixture_token_tree_top_empty_none,
+ fixture_token_tree_top_empty_brace,
+ ] {
+ for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION {
+ let tt = tt();
+ let mut span_data_table = Default::default();
+ let task = ExpandMacro {
+ data: ExpandMacroData {
+ macro_body: FlatTree::from_subtree(tt.view(), v, &mut span_data_table),
+ macro_name: Default::default(),
+ attributes: None,
+ has_global_spans: ExpnGlobals {
+ serialize: true,
+ def_site: 0,
+ call_site: 0,
+ mixed_site: 0,
+ },
+ span_data_table: Vec::new(),
},
- span_data_table: Vec::new(),
- },
- lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(),
- env: Default::default(),
- current_dir: Default::default(),
- };
-
- let json = serde_json::to_string(&task).unwrap();
- // println!("{}", json);
- let back: ExpandMacro = serde_json::from_str(&json).unwrap();
-
- assert!(
- tt == back.data.macro_body.to_subtree_resolved(v, &span_data_table),
- "version: {v}"
- );
+ lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(),
+ env: Default::default(),
+ current_dir: Default::default(),
+ };
+
+ let json = serde_json::to_string(&task).unwrap();
+ // println!("{}", json);
+ let back: ExpandMacro = serde_json::from_str(&json).unwrap();
+
+ assert_eq!(
+ tt,
+ back.data.macro_body.to_subtree_resolved(v, &span_data_table),
+ "version: {v}"
+ );
+ }
+ }
+ }
+
+ #[test]
+ #[cfg(feature = "sysroot-abi")]
+ fn test_proc_macro_rpc_works_ts() {
+ for tt in [
+ fixture_token_tree_top_many_none,
+ fixture_token_tree_top_empty_none,
+ fixture_token_tree_top_empty_brace,
+ ] {
+ let tt = tt();
+ for v in version::RUST_ANALYZER_SPAN_SUPPORT..=version::CURRENT_API_VERSION {
+ let mut span_data_table = Default::default();
+ let flat_tree = FlatTree::from_subtree(tt.view(), v, &mut span_data_table);
+ assert_eq!(
+ tt,
+ flat_tree.clone().to_subtree_resolved(v, &span_data_table),
+ "version: {v}"
+ );
+ let ts = flat_tree.to_tokenstream_resolved(v, &span_data_table, |a, b| a.cover(b));
+ let call_site = *span_data_table.first().unwrap();
+ let mut span_data_table = Default::default();
+ assert_eq!(
+ tt,
+ FlatTree::from_tokenstream(ts.clone(), v, call_site, &mut span_data_table)
+ .to_subtree_resolved(v, &span_data_table),
+ "version: {v}, ts:\n{ts:#?}"
+ );
+ }
}
}
}
diff --git a/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs b/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs
index 92e9038554..1ac8cd4006 100644
--- a/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs
+++ b/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs
@@ -85,7 +85,7 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
.collect()
}
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FlatTree {
subtree: Vec<u32>,
literal: Vec<u32>,
@@ -615,14 +615,17 @@ impl<'a, T: SpanTransformer>
root: &'a proc_macro_srv::TokenStream<T::Span>,
) {
let call_site = self.token_id_of(call_site);
- self.subtree.push(SubtreeRepr {
- open: call_site,
- close: call_site,
- kind: tt::DelimiterKind::Invisible,
- tt: [!0, !0],
- });
- self.work.push_back((0, root.len(), Some(root.iter())));
-
+ if let Some(group) = root.as_single_group() {
+ self.enqueue(group);
+ } else {
+ self.subtree.push(SubtreeRepr {
+ open: call_site,
+ close: call_site,
+ kind: tt::DelimiterKind::Invisible,
+ tt: [!0, !0],
+ });
+ self.work.push_back((0, root.len(), Some(root.iter())));
+ }
while let Some((idx, len, group)) = self.work.pop_front() {
self.group(idx, len, group);
}
@@ -962,6 +965,11 @@ impl<T: SpanTransformer> Reader<'_, T> {
};
res[i] = Some(g);
}
- res[0].take().unwrap().stream.unwrap_or_default()
+ let group = res[0].take().unwrap();
+ if group.delimiter == proc_macro_srv::Delimiter::None {
+ group.stream.unwrap_or_default()
+ } else {
+ TokenStream::new(vec![proc_macro_srv::TokenTree::Group(group)])
+ }
}
}
diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs
index c3838a8e61..93319df824 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -83,31 +83,10 @@ impl<'env> ProcMacroSrv<'env> {
}
pub fn join_spans(&self, first: Span, second: Span) -> Option<Span> {
- // We can't modify the span range for fixup spans, those are meaningful to fixup, so just
- // prefer the non-fixup span.
- if first.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER {
- return Some(second);
- }
- if second.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER {
- return Some(first);
- }
- // FIXME: Once we can talk back to the client, implement a "long join" request for anchors
- // that differ in [AstId]s as joining those spans requires resolving the AstIds.
- if first.anchor != second.anchor {
- return None;
- }
- // Differing context, we can't merge these so prefer the one that's root
- if first.ctx != second.ctx {
- if first.ctx.is_root() {
- return Some(second);
- } else if second.ctx.is_root() {
- return Some(first);
- }
- }
- Some(Span {
- range: first.range.cover(second.range),
- anchor: second.anchor,
- ctx: second.ctx,
+ first.join(second, |_, _| {
+ // FIXME: Once we can talk back to the client, implement a "long join" request for anchors
+ // that differ in [AstId]s as joining those spans requires resolving the AstIds.
+ None
})
}
}
diff --git a/crates/proc-macro-srv/src/token_stream.rs b/crates/proc-macro-srv/src/token_stream.rs
index e134a47f8c..36827d2561 100644
--- a/crates/proc-macro-srv/src/token_stream.rs
+++ b/crates/proc-macro-srv/src/token_stream.rs
@@ -40,6 +40,13 @@ impl<S> TokenStream<S> {
TokenStreamIter::new(self)
}
+ pub fn as_single_group(&self) -> Option<&Group<S>> {
+ match &**self.0 {
+ [TokenTree::Group(group)] => Some(group),
+ _ => None,
+ }
+ }
+
pub(crate) fn from_str(s: &str, span: S) -> Result<Self, String>
where
S: SpanLike + Copy,
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 731104981a..6e1a3f37ff 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -305,7 +305,7 @@ impl TargetKind {
/// If this is a valid cargo target, returns the name cargo uses in command line arguments
/// and output, otherwise None.
- /// https://docs.rs/cargo_metadata/latest/cargo_metadata/enum.TargetKind.html
+ /// <https://docs.rs/cargo_metadata/latest/cargo_metadata/enum.TargetKind.html>
pub fn as_cargo_target(self) -> Option<&'static str> {
match self {
TargetKind::Bin => Some("bin"),
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index 910bc0a96b..8eee3d1455 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -1,7 +1,7 @@
//! In rust-analyzer, we maintain a strict separation between pure abstract
//! semantic project model and a concrete model of a particular build system.
//!
-//! Pure model is represented by the [`base_db::CrateGraph`] from another crate.
+//! Pure model is represented by the `base_db::CrateGraph` from another crate.
//!
//! In this crate, we are concerned with "real world" project models.
//!
@@ -13,7 +13,10 @@
//! * Project discovery (where's the relevant Cargo.toml for the current dir).
//! * Custom build steps (`build.rs` code generation and compilation of
//! procedural macros).
-//! * Lowering of concrete model to a [`base_db::CrateGraph`]
+//! * Lowering of concrete model to a `base_db::CrateGraph`
+
+// It's useful to refer to code that is private in doc comments.
+#![allow(rustdoc::private_intra_doc_links)]
pub mod project_json;
pub mod toolchain_info {
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index d3e1f11d78..041b9accf4 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -1,6 +1,6 @@
//! `rust-project.json` file format.
//!
-//! This format is spiritually a serialization of [`base_db::CrateGraph`]. The
+//! This format is spiritually a serialization of `base_db::CrateGraph`. The
//! idea here is that people who do not use Cargo, can instead teach their build
//! system to generate `rust-project.json` which can be ingested by
//! rust-analyzer.
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index e02891eca2..10abb21ace 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1044,7 +1044,7 @@ impl ProjectWorkspace {
/// Returns `true` if the project workspace is [`Json`].
///
- /// [`Json`]: ProjectWorkspace::Json
+ /// [`Json`]: ProjectWorkspaceKind::Json
#[must_use]
pub fn is_json(&self) -> bool {
matches!(self.kind, ProjectWorkspaceKind::Json { .. })
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 767672fc2f..ed0b646685 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -10,8 +10,8 @@ use std::{
use cfg::{CfgAtom, CfgDiff};
use hir::{
- Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasSource, HirDisplay, ModuleDef, Name,
- crate_lang_items,
+ Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasCrate, HasSource, HirDisplay, ModuleDef,
+ Name, crate_lang_items,
db::{DefDatabase, ExpandDatabase, HirDatabase},
next_solver::{DbInterner, GenericArgs},
};
@@ -391,7 +391,10 @@ impl flags::AnalysisStats {
let Err(e) = db.layout_of_adt(
hir_def::AdtId::from(a),
GenericArgs::new_from_iter(interner, []),
- db.trait_environment(a.into()),
+ hir_ty::ParamEnvAndCrate {
+ param_env: db.trait_environment(a.into()),
+ krate: a.krate(db).into(),
+ },
) else {
continue;
};
diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs
index 41055272b1..2f052618cd 100644
--- a/crates/rust-analyzer/src/command.rs
+++ b/crates/rust-analyzer/src/command.rs
@@ -197,4 +197,22 @@ impl<T: Sized + Send + 'static> CommandHandle<T> {
)))
}
}
+
+ pub(crate) fn has_exited(&mut self) -> bool {
+ match self.child.0.try_wait() {
+ Ok(Some(_exit_code)) => {
+ // We have an exit code.
+ true
+ }
+ Ok(None) => {
+ // Hasn't exited yet.
+ false
+ }
+ Err(_) => {
+ // Couldn't get an exit code. Assume that we've
+ // exited.
+ true
+ }
+ }
+ }
}
diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs
index 0e96eff278..4aef5b0b7f 100644
--- a/crates/rust-analyzer/src/discover.rs
+++ b/crates/rust-analyzer/src/discover.rs
@@ -67,7 +67,7 @@ impl DiscoverCommand {
cmd.args(args);
Ok(DiscoverHandle {
- _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?,
+ handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?,
span: info_span!("discover_command").entered(),
})
}
@@ -76,7 +76,7 @@ impl DiscoverCommand {
/// A handle to a spawned [Discover].
#[derive(Debug)]
pub(crate) struct DiscoverHandle {
- _handle: CommandHandle<DiscoverProjectMessage>,
+ pub(crate) handle: CommandHandle<DiscoverProjectMessage>,
#[allow(dead_code)] // not accessed, but used to log on drop.
span: EnteredSpan,
}
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 91f7db7854..7828f50844 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -45,7 +45,7 @@ use crate::{
op_queue::{Cause, OpQueue},
reload,
target_spec::{CargoTargetSpec, ProjectJsonTargetSpec, TargetSpec},
- task_pool::{TaskPool, TaskQueue},
+ task_pool::{DeferredTaskQueue, TaskPool},
test_runner::{CargoTestHandle, CargoTestMessage},
};
@@ -121,9 +121,10 @@ pub(crate) struct GlobalState {
pub(crate) test_run_remaining_jobs: usize,
// Project loading
- pub(crate) discover_handle: Option<discover::DiscoverHandle>,
+ pub(crate) discover_handles: Vec<discover::DiscoverHandle>,
pub(crate) discover_sender: Sender<discover::DiscoverProjectMessage>,
pub(crate) discover_receiver: Receiver<discover::DiscoverProjectMessage>,
+ pub(crate) discover_jobs_active: u32,
// Debouncing channel for fetching the workspace
// we want to delay it until the VFS looks stable-ish (and thus is not currently in the middle
@@ -175,7 +176,6 @@ pub(crate) struct GlobalState {
pub(crate) fetch_build_data_queue: OpQueue<(), FetchBuildDataResponse>,
pub(crate) fetch_proc_macros_queue: OpQueue<(ChangeWithProcMacros, Vec<ProcMacroPaths>), bool>,
pub(crate) prime_caches_queue: OpQueue,
- pub(crate) discover_workspace_queue: OpQueue,
/// A deferred task queue.
///
@@ -186,7 +186,8 @@ pub(crate) struct GlobalState {
/// For certain features, such as [`GlobalState::handle_discover_msg`],
/// this queue should run only *after* [`GlobalState::process_changes`] has
/// been called.
- pub(crate) deferred_task_queue: TaskQueue,
+ pub(crate) deferred_task_queue: DeferredTaskQueue,
+
/// HACK: Workaround for https://github.com/rust-lang/rust-analyzer/issues/19709
/// This is marked true if we failed to load a crate root file at crate graph creation,
/// which will usually end up causing a bunch of incorrect diagnostics on startup.
@@ -241,9 +242,9 @@ impl GlobalState {
};
let cancellation_pool = thread::Pool::new(1);
- let task_queue = {
+ let deferred_task_queue = {
let (sender, receiver) = unbounded();
- TaskQueue { sender, receiver }
+ DeferredTaskQueue { sender, receiver }
};
let mut analysis_host = AnalysisHost::new(config.lru_parse_query_capacity());
@@ -291,9 +292,10 @@ impl GlobalState {
test_run_receiver,
test_run_remaining_jobs: 0,
- discover_handle: None,
+ discover_handles: vec![],
discover_sender,
discover_receiver,
+ discover_jobs_active: 0,
fetch_ws_receiver: None,
@@ -312,9 +314,8 @@ impl GlobalState {
fetch_proc_macros_queue: OpQueue::default(),
prime_caches_queue: OpQueue::default(),
- discover_workspace_queue: OpQueue::default(),
- deferred_task_queue: task_queue,
+ deferred_task_queue,
incomplete_crate_graph: false,
minicore: MiniCoreRustAnalyzerInternalOnly::default(),
@@ -540,10 +541,9 @@ impl GlobalState {
// didn't find anything (to make up for the lack of precision).
{
if !matches!(&workspace_structure_change, Some((.., true))) {
- _ = self
- .deferred_task_queue
- .sender
- .send(crate::main_loop::QueuedTask::CheckProcMacroSources(modified_rust_files));
+ _ = self.deferred_task_queue.sender.send(
+ crate::main_loop::DeferredTask::CheckProcMacroSources(modified_rust_files),
+ );
}
// FIXME: ideally we should only trigger a workspace fetch for non-library changes
// but something's going wrong with the source root business when we add a new local
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index 87be09dcbd..4a6544508f 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -91,7 +91,7 @@ pub(crate) fn handle_did_open_text_document(
let _ = state
.deferred_task_queue
.sender
- .send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
+ .send(crate::main_loop::DeferredTask::CheckIfIndexed(params.text_document.uri));
}
}
Ok(())
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 8b4748ddb3..77dedf1272 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -74,7 +74,7 @@ pub fn main_loop(config: Config, connection: Connection) -> anyhow::Result<()> {
enum Event {
Lsp(lsp_server::Message),
Task(Task),
- QueuedTask(QueuedTask),
+ DeferredTask(DeferredTask),
Vfs(vfs::loader::Message),
Flycheck(FlycheckMessage),
TestResult(CargoTestMessage),
@@ -89,7 +89,7 @@ impl fmt::Display for Event {
Event::Task(_) => write!(f, "Event::Task"),
Event::Vfs(_) => write!(f, "Event::Vfs"),
Event::Flycheck(_) => write!(f, "Event::Flycheck"),
- Event::QueuedTask(_) => write!(f, "Event::QueuedTask"),
+ Event::DeferredTask(_) => write!(f, "Event::DeferredTask"),
Event::TestResult(_) => write!(f, "Event::TestResult"),
Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
Event::FetchWorkspaces(_) => write!(f, "Event::SwitchWorkspaces"),
@@ -98,7 +98,7 @@ impl fmt::Display for Event {
}
#[derive(Debug)]
-pub(crate) enum QueuedTask {
+pub(crate) enum DeferredTask {
CheckIfIndexed(lsp_types::Url),
CheckProcMacroSources(Vec<FileId>),
}
@@ -164,7 +164,7 @@ impl fmt::Debug for Event {
match self {
Event::Lsp(it) => fmt::Debug::fmt(it, f),
Event::Task(it) => fmt::Debug::fmt(it, f),
- Event::QueuedTask(it) => fmt::Debug::fmt(it, f),
+ Event::DeferredTask(it) => fmt::Debug::fmt(it, f),
Event::Vfs(it) => fmt::Debug::fmt(it, f),
Event::Flycheck(it) => fmt::Debug::fmt(it, f),
Event::TestResult(it) => fmt::Debug::fmt(it, f),
@@ -279,7 +279,7 @@ impl GlobalState {
task.map(Event::Task),
recv(self.deferred_task_queue.receiver) -> task =>
- task.map(Event::QueuedTask),
+ task.map(Event::DeferredTask),
recv(self.fmt_pool.receiver) -> task =>
task.map(Event::Task),
@@ -323,12 +323,12 @@ impl GlobalState {
lsp_server::Message::Notification(not) => self.on_notification(not),
lsp_server::Message::Response(resp) => self.complete_request(resp),
},
- Event::QueuedTask(task) => {
+ Event::DeferredTask(task) => {
let _p = tracing::info_span!("GlobalState::handle_event/queued_task").entered();
- self.handle_queued_task(task);
- // Coalesce multiple task events into one loop turn
+ self.handle_deferred_task(task);
+ // Coalesce multiple deferred task events into one loop turn
while let Ok(task) = self.deferred_task_queue.receiver.try_recv() {
- self.handle_queued_task(task);
+ self.handle_deferred_task(task);
}
}
Event::Task(task) => {
@@ -531,6 +531,8 @@ impl GlobalState {
}
}
+ self.cleanup_discover_handles();
+
if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
for file_id in diagnostic_changes {
let uri = file_id_to_url(&self.vfs.read().0, file_id);
@@ -806,33 +808,34 @@ impl GlobalState {
self.report_progress("Fetching", state, msg, None, None);
}
Task::DiscoverLinkedProjects(arg) => {
- if let Some(cfg) = self.config.discover_workspace_config()
- && !self.discover_workspace_queue.op_in_progress()
- {
+ if let Some(cfg) = self.config.discover_workspace_config() {
// the clone is unfortunately necessary to avoid a borrowck error when
// `self.report_progress` is called later
let title = &cfg.progress_label.clone();
let command = cfg.command.clone();
let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
- self.report_progress(title, Progress::Begin, None, None, None);
- self.discover_workspace_queue
- .request_op("Discovering workspace".to_owned(), ());
- let _ = self.discover_workspace_queue.should_start_op();
+ if self.discover_jobs_active == 0 {
+ self.report_progress(title, Progress::Begin, None, None, None);
+ }
+ self.discover_jobs_active += 1;
let arg = match arg {
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
};
- let handle = discover.spawn(
- arg,
- &std::env::current_dir()
- .expect("Failed to get cwd during project discovery"),
- );
- self.discover_handle = Some(handle.unwrap_or_else(|e| {
- panic!("Failed to spawn project discovery command: {e}")
- }));
+ let handle = discover
+ .spawn(
+ arg,
+ &std::env::current_dir()
+ .expect("Failed to get cwd during project discovery"),
+ )
+ .unwrap_or_else(|e| {
+ panic!("Failed to spawn project discovery command: {e}")
+ });
+
+ self.discover_handles.push(handle);
}
}
Task::FetchBuildData(progress) => {
@@ -981,9 +984,9 @@ impl GlobalState {
}
}
- fn handle_queued_task(&mut self, task: QueuedTask) {
+ fn handle_deferred_task(&mut self, task: DeferredTask) {
match task {
- QueuedTask::CheckIfIndexed(uri) => {
+ DeferredTask::CheckIfIndexed(uri) => {
let snap = self.snapshot();
self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| {
@@ -1007,7 +1010,7 @@ impl GlobalState {
}
});
}
- QueuedTask::CheckProcMacroSources(modified_rust_files) => {
+ DeferredTask::CheckProcMacroSources(modified_rust_files) => {
let analysis = AssertUnwindSafe(self.snapshot().analysis);
self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, {
move |sender| {
@@ -1036,25 +1039,43 @@ impl GlobalState {
.expect("No title could be found; this is a bug");
match message {
DiscoverProjectMessage::Finished { project, buildfile } => {
- self.discover_handle = None;
- self.report_progress(&title, Progress::End, None, None, None);
- self.discover_workspace_queue.op_completed(());
+ self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
+ if self.discover_jobs_active == 0 {
+ self.report_progress(&title, Progress::End, None, None, None);
+ }
let mut config = Config::clone(&*self.config);
config.add_discovered_project_from_command(project, buildfile);
self.update_configuration(config);
}
DiscoverProjectMessage::Progress { message } => {
- self.report_progress(&title, Progress::Report, Some(message), None, None)
+ if self.discover_jobs_active > 0 {
+ self.report_progress(&title, Progress::Report, Some(message), None, None)
+ }
}
DiscoverProjectMessage::Error { error, source } => {
- self.discover_handle = None;
let message = format!("Project discovery failed: {error}");
- self.discover_workspace_queue.op_completed(());
self.show_and_log_error(message.clone(), source);
- self.report_progress(&title, Progress::End, Some(message), None, None)
+
+ self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
+ if self.discover_jobs_active == 0 {
+ self.report_progress(&title, Progress::End, Some(message), None, None)
+ }
+ }
+ }
+ }
+
+ /// Drop any discover command processes that have exited, due to
+ /// finishing or erroring.
+ fn cleanup_discover_handles(&mut self) {
+ let mut active_handles = vec![];
+
+ for mut discover_handle in self.discover_handles.drain(..) {
+ if !discover_handle.handle.has_exited() {
+ active_handles.push(discover_handle);
}
}
+ self.discover_handles = active_handles;
}
fn handle_cargo_test_msg(&mut self, message: CargoTestMessage) {
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 8876b850be..317c112365 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -74,7 +74,7 @@ impl GlobalState {
&& !self.fetch_workspaces_queue.op_in_progress()
&& !self.fetch_build_data_queue.op_in_progress()
&& !self.fetch_proc_macros_queue.op_in_progress()
- && !self.discover_workspace_queue.op_in_progress()
+ && self.discover_jobs_active == 0
&& self.vfs_progress_config_version >= self.vfs_config_version
}
@@ -297,7 +297,7 @@ impl GlobalState {
.collect();
let cargo_config = self.config.cargo(None);
let discover_command = self.config.discover_workspace_config().cloned();
- let is_quiescent = !(self.discover_workspace_queue.op_in_progress()
+ let is_quiescent = !(self.discover_jobs_active > 0
|| self.vfs_progress_config_version < self.vfs_config_version
|| !self.vfs_done);
diff --git a/crates/rust-analyzer/src/task_pool.rs b/crates/rust-analyzer/src/task_pool.rs
index c5de69bb9f..ef0feb1796 100644
--- a/crates/rust-analyzer/src/task_pool.rs
+++ b/crates/rust-analyzer/src/task_pool.rs
@@ -6,7 +6,7 @@ use std::panic::UnwindSafe;
use crossbeam_channel::Sender;
use stdx::thread::{Pool, ThreadIntent};
-use crate::main_loop::QueuedTask;
+use crate::main_loop::DeferredTask;
pub(crate) struct TaskPool<T> {
sender: Sender<T>,
@@ -45,11 +45,11 @@ impl<T> TaskPool<T> {
}
}
-/// `TaskQueue`, like its name suggests, queues tasks.
+/// `DeferredTaskQueue` holds deferred tasks.
///
-/// This should only be used if a task must run after [`GlobalState::process_changes`]
-/// has been called.
-pub(crate) struct TaskQueue {
- pub(crate) sender: crossbeam_channel::Sender<QueuedTask>,
- pub(crate) receiver: crossbeam_channel::Receiver<QueuedTask>,
+/// These are tasks that must be run after
+/// [`GlobalState::process_changes`] has been called.
+pub(crate) struct DeferredTaskQueue {
+ pub(crate) sender: crossbeam_channel::Sender<DeferredTask>,
+ pub(crate) receiver: crossbeam_channel::Receiver<DeferredTask>,
}
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index e803747998..bd49e08b10 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -44,6 +44,7 @@ pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId =
/// ErasedFileAstId used as the span for syntax node fixups. Any Span containing this file id is to be
/// considered fake.
+/// Do not modify this, it is used by the proc-macro server.
pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId =
ErasedFileAstId(pack_hash_index_and_kind(0, 0, ErasedFileAstIdKind::Fixup as u32));
@@ -700,7 +701,7 @@ impl AstIdMap {
}
}
- /// The [`AstId`] of the root node
+ /// The root node.
pub fn root(&self) -> SyntaxNodePtr {
self.arena[Idx::from_raw(RawIdx::from_u32(0))].0
}
diff --git a/crates/span/src/hygiene.rs b/crates/span/src/hygiene.rs
index 6c363825aa..6805417177 100644
--- a/crates/span/src/hygiene.rs
+++ b/crates/span/src/hygiene.rs
@@ -249,7 +249,7 @@ const _: () = {
)
}
- /// Invariant: Only [`SyntaxContext::ROOT`] has a [`None`] outer expansion.
+ /// Invariant: Only the root [`SyntaxContext`] has a [`None`] outer expansion.
// FIXME: The None case needs to encode the context crate id. We can encode that as the MSB of
// MacroCallId is reserved anyways so we can do bit tagging here just fine.
// The bigger issue is that this will cause interning to now create completely separate chains
@@ -348,7 +348,7 @@ impl SyntaxContext {
}
}
- /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context.
+ /// The root context, which is the parent of all other contexts. All `FileId`s have this context.
#[inline]
pub const fn root(edition: Edition) -> Self {
let edition = edition as u32;
diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs
index ae9e038459..cb91f49249 100644
--- a/crates/span/src/lib.rs
+++ b/crates/span/src/lib.rs
@@ -28,6 +28,33 @@ impl Span {
let range = self.range.cover(other.range);
Span { range, ..self }
}
+
+ pub fn join(
+ self,
+ other: Span,
+ differing_anchor: impl FnOnce(Span, Span) -> Option<Span>,
+ ) -> Option<Span> {
+ // We can't modify the span range for fixup spans, those are meaningful to fixup, so just
+ // prefer the non-fixup span.
+ if self.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ return Some(other);
+ }
+ if other.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ return Some(self);
+ }
+ if self.anchor != other.anchor {
+ return differing_anchor(self, other);
+ }
+ // Differing context, we can't merge these so prefer the one that's root
+ if self.ctx != other.ctx {
+ if self.ctx.is_root() {
+ return Some(other);
+ } else if other.ctx.is_root() {
+ return Some(self);
+ }
+ }
+ Some(Span { range: self.range.cover(other.range), anchor: other.anchor, ctx: other.ctx })
+ }
}
/// Spans represent a region of code, used by the IDE to be able link macro inputs and outputs
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 7346b93192..de341f0553 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -282,7 +282,7 @@ fn api_walkthrough() {
assert!(parse.errors().is_empty());
// The `tree` method returns an owned syntax node of type `SourceFile`.
- // Owned nodes are cheap: inside, they are `Rc` handles to the underling data.
+ // Owned nodes are cheap: inside, they are `Rc` handles to the underlying data.
let file: SourceFile = parse.tree();
// `SourceFile` is the root of the syntax tree. We can iterate file's items.
diff --git a/crates/test-utils/src/assert_linear.rs b/crates/test-utils/src/assert_linear.rs
index f78bf59a2f..27665a74dc 100644
--- a/crates/test-utils/src/assert_linear.rs
+++ b/crates/test-utils/src/assert_linear.rs
@@ -11,7 +11,7 @@
//! Ideally, we should use a proper "model selection" to directly compare
//! quadratic and linear models, but that sounds rather complicated:
//!
-//! > https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data
+//! > <https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data>
//!
//! We might get false positives on a VM, but never false negatives. So, if the
//! first round fails, we repeat the ordeal three more times and fail only if
diff --git a/crates/test-utils/src/fixture.rs b/crates/test-utils/src/fixture.rs
index 559894ee62..831d2b30c1 100644
--- a/crates/test-utils/src/fixture.rs
+++ b/crates/test-utils/src/fixture.rs
@@ -96,9 +96,10 @@ pub struct Fixture {
///
/// Syntax: `cfg:test,dbg=false,opt_level=2`
pub cfgs: Vec<(String, Option<String>)>,
- /// Specifies the edition of this crate. This must be used with `crate` meta. If
- /// this is not specified, ([`base_db::input::Edition::CURRENT`]) will be used.
- /// This must be used with `crate` meta.
+ /// Specifies the edition of this crate. This must be used with
+ /// `crate` meta. If this is not specified,
+ /// `base_db::input::Edition::CURRENT` will be used. This must be
+ /// used with `crate` meta.
///
/// Syntax: `edition:2021`
pub edition: Option<String>,
@@ -106,8 +107,8 @@ pub struct Fixture {
///
/// Syntax: `env:PATH=/bin,RUST_LOG=debug`
pub env: FxHashMap<String, String>,
- /// Introduces a new [source root](base_db::input::SourceRoot). This file **and
- /// the following files** will belong the new source root. This must be used
+ /// Introduces a new source root. This file **and the following
+ /// files** will belong the new source root. This must be used
/// with `crate` meta.
///
/// Use this if you want to test something that uses `SourceRoot::is_library()`
@@ -126,7 +127,7 @@ pub struct Fixture {
/// This is implied if this file belongs to a library source root.
///
/// Use this if you want to test something that checks if a crate is a workspace
- /// member via [`CrateOrigin`](base_db::input::CrateOrigin).
+ /// member via `CrateOrigin`.
///
/// Syntax: `library`
pub library: bool,
diff --git a/docs/book/README.md b/docs/book/README.md
index 11f7e8f98c..0a3161f3af 100644
--- a/docs/book/README.md
+++ b/docs/book/README.md
@@ -8,7 +8,6 @@ To run the documentation site locally:
```shell
cargo install mdbook
-cargo install mdbook-toc
cargo xtask codegen
cd docs/book
mdbook serve
diff --git a/docs/book/book.toml b/docs/book/book.toml
index c77eabda14..0978851d50 100644
--- a/docs/book/book.toml
+++ b/docs/book/book.toml
@@ -33,8 +33,3 @@ use-boolean-and = true
[output.html.fold]
enable = true
level = 3
-
-[preprocessor.toc]
-command = "mdbook-toc"
-renderer = ["html"]
-max-level = 3
diff --git a/docs/book/src/contributing/README.md b/docs/book/src/contributing/README.md
index ad2816b18a..c95a1dba62 100644
--- a/docs/book/src/contributing/README.md
+++ b/docs/book/src/contributing/README.md
@@ -26,8 +26,6 @@ Discussion happens in this Zulip stream:
<https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer>
-<!-- toc -->
-
# Issue Labels
* [good-first-issue](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22)
diff --git a/docs/book/src/contributing/architecture.md b/docs/book/src/contributing/architecture.md
index f2b6c053b0..67653ebd74 100644
--- a/docs/book/src/contributing/architecture.md
+++ b/docs/book/src/contributing/architecture.md
@@ -20,8 +20,6 @@ For older, by now mostly outdated stuff, see the [guide](./guide.md) and [anothe
![](https://user-images.githubusercontent.com/4789492/107129398-0ab70f00-687a-11eb-9bfc-d4eb023aec06.png)
-<!-- toc -->
-
On the highest level, rust-analyzer is a thing which accepts input source code from the client and produces a structured semantic model of the code.
More specifically, input data consists of a set of test files (`(PathBuf, String)` pairs) and information about project structure, captured in the so called `CrateGraph`.
diff --git a/docs/book/src/contributing/guide.md b/docs/book/src/contributing/guide.md
index 774eb5b2a5..9e944bfe0f 100644
--- a/docs/book/src/contributing/guide.md
+++ b/docs/book/src/contributing/guide.md
@@ -12,8 +12,6 @@ however, it's based on an older 2019-01-20 release (git tag [guide-2019-01]):
[guide-2019-01]: https://github.com/rust-lang/rust-analyzer/tree/guide-2019-01
[2024-01-01]: https://github.com/rust-lang/rust-analyzer/tree/2024-01-01
-<!-- toc -->
-
## The big picture
On the highest possible level, rust-analyzer is a stateful component. A client may
diff --git a/docs/book/src/contributing/lsp-extensions.md b/docs/book/src/contributing/lsp-extensions.md
index 0e91e12612..5922f0b551 100644
--- a/docs/book/src/contributing/lsp-extensions.md
+++ b/docs/book/src/contributing/lsp-extensions.md
@@ -19,8 +19,6 @@ Requests, which are likely to always remain specific to `rust-analyzer` are unde
If you want to be notified about the changes to this document, subscribe to [#4604](https://github.com/rust-lang/rust-analyzer/issues/4604).
-<!-- toc -->
-
## Configuration in `initializationOptions`
**Upstream Issue:** <https://github.com/microsoft/language-server-protocol/issues/567>
diff --git a/docs/book/src/other_editors.md b/docs/book/src/other_editors.md
index 896df52af5..f7116fc19a 100644
--- a/docs/book/src/other_editors.md
+++ b/docs/book/src/other_editors.md
@@ -6,8 +6,6 @@ Protocol](https://microsoft.github.io/language-server-protocol/).
This page assumes that you have already [installed the rust-analyzer
binary](./rust_analyzer_binary.html).
-<!-- toc -->
-
## Emacs
To use `rust-analyzer`, you need to install and enable one of the two