mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 05:13:35 +00:00
cargo clippy --fix
This commit is contained in:
parent
423c7dd23a
commit
8ce30264c8
186 changed files with 3056 additions and 3314 deletions
|
|
@ -197,10 +197,11 @@ pub(crate) fn deref_by_trait(
|
|||
// effectively bump the MSRV of rust-analyzer to 1.84 due to 1.83 and below lacking the
|
||||
// blanked impl on `Deref`.
|
||||
#[expect(clippy::overly_complex_bool_expr)]
|
||||
if use_receiver_trait && false {
|
||||
if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) {
|
||||
return Some(receiver);
|
||||
}
|
||||
if use_receiver_trait
|
||||
&& false
|
||||
&& let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate)
|
||||
{
|
||||
return Some(receiver);
|
||||
}
|
||||
// Old rustc versions might not have `Receiver` trait.
|
||||
// Fallback to `Deref` if they don't
|
||||
|
|
|
|||
|
|
@ -309,11 +309,11 @@ impl TyBuilder<hir_def::AdtId> {
|
|||
if let Some(defaults) = defaults.get(self.vec.len()..) {
|
||||
for default_ty in defaults {
|
||||
// NOTE(skip_binders): we only check if the arg type is error type.
|
||||
if let Some(x) = default_ty.skip_binders().ty(Interner) {
|
||||
if x.is_unknown() {
|
||||
self.vec.push(fallback().cast(Interner));
|
||||
continue;
|
||||
}
|
||||
if let Some(x) = default_ty.skip_binders().ty(Interner)
|
||||
&& x.is_unknown()
|
||||
{
|
||||
self.vec.push(fallback().cast(Interner));
|
||||
continue;
|
||||
}
|
||||
// Each default can only depend on the previous parameters.
|
||||
self.vec.push(default_ty.clone().substitute(Interner, &*self.vec).cast(Interner));
|
||||
|
|
|
|||
|
|
@ -83,34 +83,34 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
|
||||
}
|
||||
fn discriminant_type(&self, ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
|
||||
if let chalk_ir::TyKind::Adt(id, _) = ty.kind(Interner) {
|
||||
if let hir_def::AdtId::EnumId(e) = id.0 {
|
||||
let enum_data = self.db.enum_signature(e);
|
||||
let ty = enum_data.repr.unwrap_or_default().discr_type();
|
||||
return chalk_ir::TyKind::Scalar(match ty {
|
||||
hir_def::layout::IntegerType::Pointer(is_signed) => match is_signed {
|
||||
true => chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize),
|
||||
false => chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize),
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(size, is_signed) => match is_signed {
|
||||
true => chalk_ir::Scalar::Int(match size {
|
||||
hir_def::layout::Integer::I8 => chalk_ir::IntTy::I8,
|
||||
hir_def::layout::Integer::I16 => chalk_ir::IntTy::I16,
|
||||
hir_def::layout::Integer::I32 => chalk_ir::IntTy::I32,
|
||||
hir_def::layout::Integer::I64 => chalk_ir::IntTy::I64,
|
||||
hir_def::layout::Integer::I128 => chalk_ir::IntTy::I128,
|
||||
}),
|
||||
false => chalk_ir::Scalar::Uint(match size {
|
||||
hir_def::layout::Integer::I8 => chalk_ir::UintTy::U8,
|
||||
hir_def::layout::Integer::I16 => chalk_ir::UintTy::U16,
|
||||
hir_def::layout::Integer::I32 => chalk_ir::UintTy::U32,
|
||||
hir_def::layout::Integer::I64 => chalk_ir::UintTy::U64,
|
||||
hir_def::layout::Integer::I128 => chalk_ir::UintTy::U128,
|
||||
}),
|
||||
},
|
||||
})
|
||||
.intern(Interner);
|
||||
}
|
||||
if let chalk_ir::TyKind::Adt(id, _) = ty.kind(Interner)
|
||||
&& let hir_def::AdtId::EnumId(e) = id.0
|
||||
{
|
||||
let enum_data = self.db.enum_signature(e);
|
||||
let ty = enum_data.repr.unwrap_or_default().discr_type();
|
||||
return chalk_ir::TyKind::Scalar(match ty {
|
||||
hir_def::layout::IntegerType::Pointer(is_signed) => match is_signed {
|
||||
true => chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize),
|
||||
false => chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize),
|
||||
},
|
||||
hir_def::layout::IntegerType::Fixed(size, is_signed) => match is_signed {
|
||||
true => chalk_ir::Scalar::Int(match size {
|
||||
hir_def::layout::Integer::I8 => chalk_ir::IntTy::I8,
|
||||
hir_def::layout::Integer::I16 => chalk_ir::IntTy::I16,
|
||||
hir_def::layout::Integer::I32 => chalk_ir::IntTy::I32,
|
||||
hir_def::layout::Integer::I64 => chalk_ir::IntTy::I64,
|
||||
hir_def::layout::Integer::I128 => chalk_ir::IntTy::I128,
|
||||
}),
|
||||
false => chalk_ir::Scalar::Uint(match size {
|
||||
hir_def::layout::Integer::I8 => chalk_ir::UintTy::U8,
|
||||
hir_def::layout::Integer::I16 => chalk_ir::UintTy::U16,
|
||||
hir_def::layout::Integer::I32 => chalk_ir::UintTy::U32,
|
||||
hir_def::layout::Integer::I64 => chalk_ir::UintTy::U64,
|
||||
hir_def::layout::Integer::I128 => chalk_ir::UintTy::U128,
|
||||
}),
|
||||
},
|
||||
})
|
||||
.intern(Interner);
|
||||
}
|
||||
chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8)).intern(Interner)
|
||||
}
|
||||
|
|
@ -142,10 +142,10 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
) -> Option<chalk_ir::TyVariableKind> {
|
||||
if let TyKind::BoundVar(bv) = ty.kind(Interner) {
|
||||
let binders = binders.as_slice(Interner);
|
||||
if bv.debruijn == DebruijnIndex::INNERMOST {
|
||||
if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
|
||||
return Some(tk);
|
||||
}
|
||||
if bv.debruijn == DebruijnIndex::INNERMOST
|
||||
&& let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind
|
||||
{
|
||||
return Some(tk);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -342,10 +342,10 @@ pub(crate) fn eval_to_const(
|
|||
return c;
|
||||
}
|
||||
}
|
||||
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) {
|
||||
if let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None) {
|
||||
return result;
|
||||
}
|
||||
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr)
|
||||
&& let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
unknown_const(infer[expr].clone())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -657,10 +657,10 @@ impl<'a> DeclValidator<'a> {
|
|||
}
|
||||
|
||||
fn is_trait_impl_container(&self, container_id: ItemContainerId) -> bool {
|
||||
if let ItemContainerId::ImplId(impl_id) = container_id {
|
||||
if self.db.impl_trait(impl_id).is_some() {
|
||||
return true;
|
||||
}
|
||||
if let ItemContainerId::ImplId(impl_id) = container_id
|
||||
&& self.db.impl_trait(impl_id).is_some()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -528,15 +528,15 @@ impl FilterMapNextChecker {
|
|||
return None;
|
||||
}
|
||||
|
||||
if *function_id == self.next_function_id? {
|
||||
if let Some(prev_filter_map_expr_id) = self.prev_filter_map_expr_id {
|
||||
let is_dyn_trait = self
|
||||
.prev_receiver_ty
|
||||
.as_ref()
|
||||
.is_some_and(|it| it.strip_references().dyn_trait().is_some());
|
||||
if *receiver_expr_id == prev_filter_map_expr_id && !is_dyn_trait {
|
||||
return Some(());
|
||||
}
|
||||
if *function_id == self.next_function_id?
|
||||
&& let Some(prev_filter_map_expr_id) = self.prev_filter_map_expr_id
|
||||
{
|
||||
let is_dyn_trait = self
|
||||
.prev_receiver_ty
|
||||
.as_ref()
|
||||
.is_some_and(|it| it.strip_references().dyn_trait().is_some());
|
||||
if *receiver_expr_id == prev_filter_map_expr_id && !is_dyn_trait {
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,10 +382,10 @@ impl HirDisplay for Pat {
|
|||
let subpats = (0..num_fields).map(|i| {
|
||||
WriteWith(move |f| {
|
||||
let fid = LocalFieldId::from_raw((i as u32).into());
|
||||
if let Some(p) = subpatterns.get(i) {
|
||||
if p.field == fid {
|
||||
return p.pattern.hir_fmt(f);
|
||||
}
|
||||
if let Some(p) = subpatterns.get(i)
|
||||
&& p.field == fid
|
||||
{
|
||||
return p.pattern.hir_fmt(f);
|
||||
}
|
||||
if let Some(p) = subpatterns.iter().find(|p| p.field == fid) {
|
||||
p.pattern.hir_fmt(f)
|
||||
|
|
|
|||
|
|
@ -272,10 +272,10 @@ impl<'db> UnsafeVisitor<'db> {
|
|||
if let Some(func) = callee.as_fn_def(self.db) {
|
||||
self.check_call(current, func);
|
||||
}
|
||||
if let TyKind::Function(fn_ptr) = callee.kind(Interner) {
|
||||
if fn_ptr.sig.safety == chalk_ir::Safety::Unsafe {
|
||||
self.on_unsafe_op(current.into(), UnsafetyReason::UnsafeFnCall);
|
||||
}
|
||||
if let TyKind::Function(fn_ptr) = callee.kind(Interner)
|
||||
&& fn_ptr.sig.safety == chalk_ir::Safety::Unsafe
|
||||
{
|
||||
self.on_unsafe_op(current.into(), UnsafetyReason::UnsafeFnCall);
|
||||
}
|
||||
}
|
||||
Expr::Path(path) => {
|
||||
|
|
@ -346,12 +346,11 @@ impl<'db> UnsafeVisitor<'db> {
|
|||
Expr::Cast { .. } => self.inside_assignment = inside_assignment,
|
||||
Expr::Field { .. } => {
|
||||
self.inside_assignment = inside_assignment;
|
||||
if !inside_assignment {
|
||||
if let Some(Either::Left(FieldId { parent: VariantId::UnionId(_), .. })) =
|
||||
if !inside_assignment
|
||||
&& let Some(Either::Left(FieldId { parent: VariantId::UnionId(_), .. })) =
|
||||
self.infer.field_resolution(current)
|
||||
{
|
||||
self.on_unsafe_op(current.into(), UnsafetyReason::UnionField);
|
||||
}
|
||||
{
|
||||
self.on_unsafe_op(current.into(), UnsafetyReason::UnionField);
|
||||
}
|
||||
}
|
||||
Expr::Unsafe { statements, .. } => {
|
||||
|
|
|
|||
|
|
@ -608,48 +608,46 @@ impl HirDisplay for ProjectionTy {
|
|||
// if we are projection on a type parameter, check if the projection target has bounds
|
||||
// itself, if so, we render them directly as `impl Bound` instead of the less useful
|
||||
// `<Param as Trait>::Assoc`
|
||||
if !f.display_kind.is_source_code() {
|
||||
if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
|
||||
if !f.bounds_formatting_ctx.contains(self) {
|
||||
let db = f.db;
|
||||
let id = from_placeholder_idx(db, *idx);
|
||||
let generics = generics(db, id.parent);
|
||||
if !f.display_kind.is_source_code()
|
||||
&& let TyKind::Placeholder(idx) = self_ty.kind(Interner)
|
||||
&& !f.bounds_formatting_ctx.contains(self)
|
||||
{
|
||||
let db = f.db;
|
||||
let id = from_placeholder_idx(db, *idx);
|
||||
let generics = generics(db, id.parent);
|
||||
|
||||
let substs = generics.placeholder_subst(db);
|
||||
let bounds = db
|
||||
.generic_predicates(id.parent)
|
||||
.iter()
|
||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||
.filter(|wc| {
|
||||
let ty = match wc.skip_binders() {
|
||||
WhereClause::Implemented(tr) => tr.self_type_parameter(Interner),
|
||||
WhereClause::TypeOutlives(t) => t.ty.clone(),
|
||||
// We shouldn't be here if these exist
|
||||
WhereClause::AliasEq(_) | WhereClause::LifetimeOutlives(_) => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let TyKind::Alias(AliasTy::Projection(proj)) = ty.kind(Interner) else {
|
||||
return false;
|
||||
};
|
||||
proj == self
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if !bounds.is_empty() {
|
||||
return f.format_bounds_with(self.clone(), |f| {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(
|
||||
&TyKind::Alias(AliasTy::Projection(self.clone()))
|
||||
.intern(Interner),
|
||||
),
|
||||
&bounds,
|
||||
SizedByDefault::NotSized,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
let substs = generics.placeholder_subst(db);
|
||||
let bounds = db
|
||||
.generic_predicates(id.parent)
|
||||
.iter()
|
||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||
.filter(|wc| {
|
||||
let ty = match wc.skip_binders() {
|
||||
WhereClause::Implemented(tr) => tr.self_type_parameter(Interner),
|
||||
WhereClause::TypeOutlives(t) => t.ty.clone(),
|
||||
// We shouldn't be here if these exist
|
||||
WhereClause::AliasEq(_) | WhereClause::LifetimeOutlives(_) => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let TyKind::Alias(AliasTy::Projection(proj)) = ty.kind(Interner) else {
|
||||
return false;
|
||||
};
|
||||
proj == self
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if !bounds.is_empty() {
|
||||
return f.format_bounds_with(self.clone(), |f| {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(
|
||||
&TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner),
|
||||
),
|
||||
&bounds,
|
||||
SizedByDefault::NotSized,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1860,18 +1858,13 @@ fn write_bounds_like_dyn_trait(
|
|||
write!(f, "{}", f.db.trait_signature(trait_).name.display(f.db, f.edition()))?;
|
||||
f.end_location_link();
|
||||
if is_fn_trait {
|
||||
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
|
||||
if let Some(args) =
|
||||
if let [self_, params @ ..] = trait_ref.substitution.as_slice(Interner)
|
||||
&& let Some(args) =
|
||||
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
|
||||
{
|
||||
write!(f, "(")?;
|
||||
hir_fmt_generic_arguments(
|
||||
f,
|
||||
args.as_slice(Interner),
|
||||
self_.ty(Interner),
|
||||
)?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
{
|
||||
write!(f, "(")?;
|
||||
hir_fmt_generic_arguments(f, args.as_slice(Interner), self_.ty(Interner))?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
} else {
|
||||
let params = generic_args_sans_defaults(
|
||||
|
|
@ -1879,13 +1872,13 @@ fn write_bounds_like_dyn_trait(
|
|||
Some(trait_.into()),
|
||||
trait_ref.substitution.as_slice(Interner),
|
||||
);
|
||||
if let [self_, params @ ..] = params {
|
||||
if !params.is_empty() {
|
||||
write!(f, "<")?;
|
||||
hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
|
||||
// there might be assoc type bindings, so we leave the angle brackets open
|
||||
angle_open = true;
|
||||
}
|
||||
if let [self_, params @ ..] = params
|
||||
&& !params.is_empty()
|
||||
{
|
||||
write!(f, "<")?;
|
||||
hir_fmt_generic_arguments(f, params, self_.ty(Interner))?;
|
||||
// there might be assoc type bindings, so we leave the angle brackets open
|
||||
angle_open = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2443,11 +2436,11 @@ impl HirDisplayWithExpressionStore for Path {
|
|||
generic_args.args[0].hir_fmt(f, store)?;
|
||||
}
|
||||
}
|
||||
if let Some(ret) = generic_args.bindings[0].type_ref {
|
||||
if !matches!(&store[ret], TypeRef::Tuple(v) if v.is_empty()) {
|
||||
write!(f, " -> ")?;
|
||||
ret.hir_fmt(f, store)?;
|
||||
}
|
||||
if let Some(ret) = generic_args.bindings[0].type_ref
|
||||
&& !matches!(&store[ret], TypeRef::Tuple(v) if v.is_empty())
|
||||
{
|
||||
write!(f, " -> ")?;
|
||||
ret.hir_fmt(f, store)?;
|
||||
}
|
||||
}
|
||||
hir_def::expr_store::path::GenericArgsParentheses::No => {
|
||||
|
|
|
|||
|
|
@ -136,16 +136,15 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
|
|||
let predicates = predicates.iter().map(|p| p.skip_binders().skip_binders().clone());
|
||||
elaborate_clause_supertraits(db, predicates).any(|pred| match pred {
|
||||
WhereClause::Implemented(trait_ref) => {
|
||||
if from_chalk_trait_id(trait_ref.trait_id) == sized {
|
||||
if let TyKind::BoundVar(it) =
|
||||
if from_chalk_trait_id(trait_ref.trait_id) == sized
|
||||
&& let TyKind::BoundVar(it) =
|
||||
*trait_ref.self_type_parameter(Interner).kind(Interner)
|
||||
{
|
||||
// Since `generic_predicates` is `Binder<Binder<..>>`, the `DebrujinIndex` of
|
||||
// self-parameter is `1`
|
||||
return it
|
||||
.index_if_bound_at(DebruijnIndex::ONE)
|
||||
.is_some_and(|idx| idx == trait_self_param_idx);
|
||||
}
|
||||
{
|
||||
// Since `generic_predicates` is `Binder<Binder<..>>`, the `DebrujinIndex` of
|
||||
// self-parameter is `1`
|
||||
return it
|
||||
.index_if_bound_at(DebruijnIndex::ONE)
|
||||
.is_some_and(|idx| idx == trait_self_param_idx);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -401,10 +400,10 @@ where
|
|||
cb(MethodViolationCode::ReferencesSelfOutput)?;
|
||||
}
|
||||
|
||||
if !func_data.is_async() {
|
||||
if let Some(mvc) = contains_illegal_impl_trait_in_trait(db, &sig) {
|
||||
cb(mvc)?;
|
||||
}
|
||||
if !func_data.is_async()
|
||||
&& let Some(mvc) = contains_illegal_impl_trait_in_trait(db, &sig)
|
||||
{
|
||||
cb(mvc)?;
|
||||
}
|
||||
|
||||
let generic_params = db.generic_params(func.into());
|
||||
|
|
|
|||
|
|
@ -902,12 +902,12 @@ impl<'db> InferenceContext<'db> {
|
|||
return false;
|
||||
}
|
||||
|
||||
if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic {
|
||||
if let Some(ty) = field_with_same_name {
|
||||
*ty = table.resolve_completely(ty.clone());
|
||||
if ty.contains_unknown() {
|
||||
*field_with_same_name = None;
|
||||
}
|
||||
if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic
|
||||
&& let Some(ty) = field_with_same_name
|
||||
{
|
||||
*ty = table.resolve_completely(ty.clone());
|
||||
if ty.contains_unknown() {
|
||||
*field_with_same_name = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1010,12 +1010,12 @@ impl<'db> InferenceContext<'db> {
|
|||
param_tys.push(va_list_ty);
|
||||
}
|
||||
let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
|
||||
if let Some(self_param) = self.body.self_param {
|
||||
if let Some(ty) = param_tys.next() {
|
||||
let ty = self.insert_type_vars(ty);
|
||||
let ty = self.normalize_associated_types_in(ty);
|
||||
self.write_binding_ty(self_param, ty);
|
||||
}
|
||||
if let Some(self_param) = self.body.self_param
|
||||
&& let Some(ty) = param_tys.next()
|
||||
{
|
||||
let ty = self.insert_type_vars(ty);
|
||||
let ty = self.normalize_associated_types_in(ty);
|
||||
self.write_binding_ty(self_param, ty);
|
||||
}
|
||||
let mut tait_candidates = FxHashSet::default();
|
||||
for (ty, pat) in param_tys.zip(&*self.body.params) {
|
||||
|
|
@ -1199,20 +1199,19 @@ impl<'db> InferenceContext<'db> {
|
|||
) -> std::ops::ControlFlow<Self::BreakTy> {
|
||||
let ty = self.table.resolve_ty_shallow(ty);
|
||||
|
||||
if let TyKind::OpaqueType(id, _) = ty.kind(Interner) {
|
||||
if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
|
||||
if let TyKind::OpaqueType(id, _) = ty.kind(Interner)
|
||||
&& let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
|
||||
self.db.lookup_intern_impl_trait_id((*id).into())
|
||||
{
|
||||
let loc = self.db.lookup_intern_type_alias(alias_id);
|
||||
match loc.container {
|
||||
ItemContainerId::ImplId(impl_id) => {
|
||||
self.assocs.insert(*id, (impl_id, ty.clone()));
|
||||
}
|
||||
ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
|
||||
self.non_assocs.insert(*id, ty.clone());
|
||||
}
|
||||
_ => {}
|
||||
{
|
||||
let loc = self.db.lookup_intern_type_alias(alias_id);
|
||||
match loc.container {
|
||||
ItemContainerId::ImplId(impl_id) => {
|
||||
self.assocs.insert(*id, (impl_id, ty.clone()));
|
||||
}
|
||||
ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
|
||||
self.non_assocs.insert(*id, ty.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -233,26 +233,25 @@ impl CastCheck {
|
|||
F: FnMut(ExprId, Vec<Adjustment>),
|
||||
{
|
||||
// Mutability order is opposite to rustc. `Mut < Not`
|
||||
if m_expr <= m_cast {
|
||||
if let TyKind::Array(ety, _) = t_expr.kind(Interner) {
|
||||
// Coerce to a raw pointer so that we generate RawPtr in MIR.
|
||||
let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner);
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &array_ptr_type, CoerceNever::Yes)
|
||||
{
|
||||
apply_adjustments(self.source_expr, adj);
|
||||
} else {
|
||||
never!(
|
||||
"could not cast from reference to array to pointer to array ({:?} to {:?})",
|
||||
self.expr_ty,
|
||||
array_ptr_type
|
||||
);
|
||||
}
|
||||
if m_expr <= m_cast
|
||||
&& let TyKind::Array(ety, _) = t_expr.kind(Interner)
|
||||
{
|
||||
// Coerce to a raw pointer so that we generate RawPtr in MIR.
|
||||
let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner);
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &array_ptr_type, CoerceNever::Yes) {
|
||||
apply_adjustments(self.source_expr, adj);
|
||||
} else {
|
||||
never!(
|
||||
"could not cast from reference to array to pointer to array ({:?} to {:?})",
|
||||
self.expr_ty,
|
||||
array_ptr_type
|
||||
);
|
||||
}
|
||||
|
||||
// This is a less strict condition than rustc's `demand_eqtype`,
|
||||
// but false negative is better than false positive
|
||||
if table.coerce(ety, t_cast, CoerceNever::Yes).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
// This is a less strict condition than rustc's `demand_eqtype`,
|
||||
// but false negative is better than false positive
|
||||
if table.coerce(ety, t_cast, CoerceNever::Yes).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,12 +176,12 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
|
||||
// Deduction based on the expected `dyn Fn` is done separately.
|
||||
if let TyKind::Dyn(dyn_ty) = expected_ty.kind(Interner) {
|
||||
if let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty) {
|
||||
let expected_sig_ty = TyKind::Function(sig).intern(Interner);
|
||||
if let TyKind::Dyn(dyn_ty) = expected_ty.kind(Interner)
|
||||
&& let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty)
|
||||
{
|
||||
let expected_sig_ty = TyKind::Function(sig).intern(Interner);
|
||||
|
||||
self.unify(sig_ty, &expected_sig_ty);
|
||||
}
|
||||
self.unify(sig_ty, &expected_sig_ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -208,14 +208,13 @@ impl InferenceContext<'_> {
|
|||
alias: AliasTy::Projection(projection_ty),
|
||||
ty: projected_ty,
|
||||
}) = bound.skip_binders()
|
||||
{
|
||||
if let Some(sig) = self.deduce_sig_from_projection(
|
||||
&& let Some(sig) = self.deduce_sig_from_projection(
|
||||
closure_kind,
|
||||
projection_ty,
|
||||
projected_ty,
|
||||
) {
|
||||
return Some(sig);
|
||||
}
|
||||
)
|
||||
{
|
||||
return Some(sig);
|
||||
}
|
||||
None
|
||||
});
|
||||
|
|
@ -254,55 +253,44 @@ impl InferenceContext<'_> {
|
|||
let mut expected_kind = None;
|
||||
|
||||
for clause in elaborate_clause_supertraits(self.db, clauses.rev()) {
|
||||
if expected_sig.is_none() {
|
||||
if let WhereClause::AliasEq(AliasEq {
|
||||
alias: AliasTy::Projection(projection),
|
||||
ty,
|
||||
}) = &clause
|
||||
{
|
||||
let inferred_sig =
|
||||
self.deduce_sig_from_projection(closure_kind, projection, ty);
|
||||
// Make sure that we didn't infer a signature that mentions itself.
|
||||
// This can happen when we elaborate certain supertrait bounds that
|
||||
// mention projections containing the `Self` type. See rust-lang/rust#105401.
|
||||
struct MentionsTy<'a> {
|
||||
expected_ty: &'a Ty,
|
||||
if expected_sig.is_none()
|
||||
&& let WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection), ty }) =
|
||||
&clause
|
||||
{
|
||||
let inferred_sig = self.deduce_sig_from_projection(closure_kind, projection, ty);
|
||||
// Make sure that we didn't infer a signature that mentions itself.
|
||||
// This can happen when we elaborate certain supertrait bounds that
|
||||
// mention projections containing the `Self` type. See rust-lang/rust#105401.
|
||||
struct MentionsTy<'a> {
|
||||
expected_ty: &'a Ty,
|
||||
}
|
||||
impl TypeVisitor<Interner> for MentionsTy<'_> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn interner(&self) -> Interner {
|
||||
Interner
|
||||
}
|
||||
impl TypeVisitor<Interner> for MentionsTy<'_> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn interner(&self) -> Interner {
|
||||
Interner
|
||||
}
|
||||
|
||||
fn as_dyn(
|
||||
&mut self,
|
||||
) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy>
|
||||
{
|
||||
self
|
||||
}
|
||||
|
||||
fn visit_ty(
|
||||
&mut self,
|
||||
t: &Ty,
|
||||
db: chalk_ir::DebruijnIndex,
|
||||
) -> ControlFlow<()> {
|
||||
if t == self.expected_ty {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
t.super_visit_with(self, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
if inferred_sig
|
||||
.visit_with(
|
||||
&mut MentionsTy { expected_ty },
|
||||
chalk_ir::DebruijnIndex::INNERMOST,
|
||||
)
|
||||
.is_continue()
|
||||
fn as_dyn(
|
||||
&mut self,
|
||||
) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy>
|
||||
{
|
||||
expected_sig = inferred_sig;
|
||||
self
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &Ty, db: chalk_ir::DebruijnIndex) -> ControlFlow<()> {
|
||||
if t == self.expected_ty {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
t.super_visit_with(self, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
if inferred_sig
|
||||
.visit_with(&mut MentionsTy { expected_ty }, chalk_ir::DebruijnIndex::INNERMOST)
|
||||
.is_continue()
|
||||
{
|
||||
expected_sig = inferred_sig;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -617,11 +605,10 @@ impl HirPlace {
|
|||
if let CaptureKind::ByRef(BorrowKind::Mut {
|
||||
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
||||
}) = current_capture
|
||||
&& self.projections[len..].contains(&ProjectionElem::Deref)
|
||||
{
|
||||
if self.projections[len..].contains(&ProjectionElem::Deref) {
|
||||
current_capture =
|
||||
CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture });
|
||||
}
|
||||
current_capture =
|
||||
CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture });
|
||||
}
|
||||
current_capture
|
||||
}
|
||||
|
|
@ -1076,12 +1063,11 @@ impl InferenceContext<'_> {
|
|||
Mutability::Mut => CaptureKind::ByRef(BorrowKind::Mut { kind: MutBorrowKind::Default }),
|
||||
Mutability::Not => CaptureKind::ByRef(BorrowKind::Shared),
|
||||
};
|
||||
if let Some(place) = self.place_of_expr_without_adjust(tgt_expr) {
|
||||
if let Some(place) =
|
||||
if let Some(place) = self.place_of_expr_without_adjust(tgt_expr)
|
||||
&& let Some(place) =
|
||||
apply_adjusts_to_place(&mut self.current_capture_span_stack, place, rest)
|
||||
{
|
||||
self.add_capture(place, capture_kind);
|
||||
}
|
||||
{
|
||||
self.add_capture(place, capture_kind);
|
||||
}
|
||||
self.walk_expr_with_adjust(tgt_expr, rest);
|
||||
}
|
||||
|
|
@ -1169,15 +1155,15 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
}
|
||||
self.walk_expr(*expr);
|
||||
if let Some(discr_place) = self.place_of_expr(*expr) {
|
||||
if self.is_upvar(&discr_place) {
|
||||
let mut capture_mode = None;
|
||||
for arm in arms.iter() {
|
||||
self.walk_pat(&mut capture_mode, arm.pat);
|
||||
}
|
||||
if let Some(c) = capture_mode {
|
||||
self.push_capture(discr_place, c);
|
||||
}
|
||||
if let Some(discr_place) = self.place_of_expr(*expr)
|
||||
&& self.is_upvar(&discr_place)
|
||||
{
|
||||
let mut capture_mode = None;
|
||||
for arm in arms.iter() {
|
||||
self.walk_pat(&mut capture_mode, arm.pat);
|
||||
}
|
||||
if let Some(c) = capture_mode {
|
||||
self.push_capture(discr_place, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1209,13 +1195,11 @@ impl InferenceContext<'_> {
|
|||
let mutability = 'b: {
|
||||
if let Some(deref_trait) =
|
||||
self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
|
||||
{
|
||||
if let Some(deref_fn) = deref_trait
|
||||
&& let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
false
|
||||
};
|
||||
|
|
@ -1405,10 +1389,10 @@ impl InferenceContext<'_> {
|
|||
|
||||
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty {
|
||||
let mut ty = None;
|
||||
if let Some(it) = self.result.expr_adjustments.get(&e) {
|
||||
if let Some(it) = it.last() {
|
||||
ty = Some(it.target.clone());
|
||||
}
|
||||
if let Some(it) = self.result.expr_adjustments.get(&e)
|
||||
&& let Some(it) = it.last()
|
||||
{
|
||||
ty = Some(it.target.clone());
|
||||
}
|
||||
ty.unwrap_or_else(|| self.expr_ty(e))
|
||||
}
|
||||
|
|
@ -1793,10 +1777,10 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
|
||||
pub(super) fn add_current_closure_dependency(&mut self, dep: ClosureId) {
|
||||
if let Some(c) = self.current_closure {
|
||||
if !dep_creates_cycle(&self.closure_dependencies, &mut FxHashSet::default(), c, dep) {
|
||||
self.closure_dependencies.entry(c).or_default().push(dep);
|
||||
}
|
||||
if let Some(c) = self.current_closure
|
||||
&& !dep_creates_cycle(&self.closure_dependencies, &mut FxHashSet::default(), c, dep)
|
||||
{
|
||||
self.closure_dependencies.entry(c).or_default().push(dep);
|
||||
}
|
||||
|
||||
fn dep_creates_cycle(
|
||||
|
|
|
|||
|
|
@ -164,14 +164,14 @@ impl CoerceMany {
|
|||
// - [Comment from rustc](https://github.com/rust-lang/rust/blob/5ff18d0eaefd1bd9ab8ec33dab2404a44e7631ed/compiler/rustc_hir_typeck/src/coercion.rs#L1334-L1335)
|
||||
// First try to coerce the new expression to the type of the previous ones,
|
||||
// but only if the new expression has no coercion already applied to it.
|
||||
if expr.is_none_or(|expr| !ctx.result.expr_adjustments.contains_key(&expr)) {
|
||||
if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) {
|
||||
self.final_ty = Some(res);
|
||||
if let Some(expr) = expr {
|
||||
self.expressions.push(expr);
|
||||
}
|
||||
return;
|
||||
if expr.is_none_or(|expr| !ctx.result.expr_adjustments.contains_key(&expr))
|
||||
&& let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes)
|
||||
{
|
||||
self.final_ty = Some(res);
|
||||
if let Some(expr) = expr {
|
||||
self.expressions.push(expr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok((adjustments, res)) =
|
||||
|
|
@ -322,18 +322,13 @@ impl InferenceTable<'_> {
|
|||
// If we are coercing into a TAIT, coerce into its proxy inference var, instead.
|
||||
let mut to_ty = to_ty;
|
||||
let _to;
|
||||
if let Some(tait_table) = &self.tait_coercion_table {
|
||||
if let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner) {
|
||||
if !matches!(
|
||||
from_ty.kind(Interner),
|
||||
TyKind::InferenceVar(..) | TyKind::OpaqueType(..)
|
||||
) {
|
||||
if let Some(ty) = tait_table.get(opaque_ty_id) {
|
||||
_to = ty.clone();
|
||||
to_ty = &_to;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(tait_table) = &self.tait_coercion_table
|
||||
&& let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner)
|
||||
&& !matches!(from_ty.kind(Interner), TyKind::InferenceVar(..) | TyKind::OpaqueType(..))
|
||||
&& let Some(ty) = tait_table.get(opaque_ty_id)
|
||||
{
|
||||
_to = ty.clone();
|
||||
to_ty = &_to;
|
||||
}
|
||||
|
||||
// Consider coercing the subtype to a DST
|
||||
|
|
@ -594,14 +589,13 @@ impl InferenceTable<'_> {
|
|||
F: FnOnce(Ty) -> Vec<Adjustment>,
|
||||
G: FnOnce(Ty) -> Vec<Adjustment>,
|
||||
{
|
||||
if let TyKind::Function(to_fn_ptr) = to_ty.kind(Interner) {
|
||||
if let (chalk_ir::Safety::Safe, chalk_ir::Safety::Unsafe) =
|
||||
if let TyKind::Function(to_fn_ptr) = to_ty.kind(Interner)
|
||||
&& let (chalk_ir::Safety::Safe, chalk_ir::Safety::Unsafe) =
|
||||
(from_fn_ptr.sig.safety, to_fn_ptr.sig.safety)
|
||||
{
|
||||
let from_unsafe =
|
||||
TyKind::Function(safe_to_unsafe_fn_ty(from_fn_ptr.clone())).intern(Interner);
|
||||
return self.unify_and(&from_unsafe, to_ty, to_unsafe);
|
||||
}
|
||||
{
|
||||
let from_unsafe =
|
||||
TyKind::Function(safe_to_unsafe_fn_ty(from_fn_ptr.clone())).intern(Interner);
|
||||
return self.unify_and(&from_unsafe, to_ty, to_unsafe);
|
||||
}
|
||||
self.unify_and(&from_ty, to_ty, normal)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -653,19 +653,18 @@ impl InferenceContext<'_> {
|
|||
// FIXME: Note down method resolution her
|
||||
match op {
|
||||
UnaryOp::Deref => {
|
||||
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
||||
if let Some(deref_fn) = deref_trait
|
||||
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref)
|
||||
&& let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref))
|
||||
{
|
||||
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
|
||||
// the mutability is not wrong, and will be fixed in `self.infer_mut`).
|
||||
self.write_method_resolution(
|
||||
tgt_expr,
|
||||
deref_fn,
|
||||
Substitution::empty(Interner),
|
||||
);
|
||||
}
|
||||
{
|
||||
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
|
||||
// the mutability is not wrong, and will be fixed in `self.infer_mut`).
|
||||
self.write_method_resolution(
|
||||
tgt_expr,
|
||||
deref_fn,
|
||||
Substitution::empty(Interner),
|
||||
);
|
||||
}
|
||||
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
|
||||
self.resolve_ty_shallow(derefed)
|
||||
|
|
@ -1387,28 +1386,28 @@ impl InferenceContext<'_> {
|
|||
let ret_ty = match method_ty.callable_sig(self.db) {
|
||||
Some(sig) => {
|
||||
let p_left = &sig.params()[0];
|
||||
if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. }) {
|
||||
if let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner) {
|
||||
self.write_expr_adj(
|
||||
lhs,
|
||||
Box::new([Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
|
||||
target: p_left.clone(),
|
||||
}]),
|
||||
);
|
||||
}
|
||||
if matches!(op, BinaryOp::CmpOp(..) | BinaryOp::Assignment { .. })
|
||||
&& let TyKind::Ref(mtbl, lt, _) = p_left.kind(Interner)
|
||||
{
|
||||
self.write_expr_adj(
|
||||
lhs,
|
||||
Box::new([Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
|
||||
target: p_left.clone(),
|
||||
}]),
|
||||
);
|
||||
}
|
||||
let p_right = &sig.params()[1];
|
||||
if matches!(op, BinaryOp::CmpOp(..)) {
|
||||
if let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner) {
|
||||
self.write_expr_adj(
|
||||
rhs,
|
||||
Box::new([Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
|
||||
target: p_right.clone(),
|
||||
}]),
|
||||
);
|
||||
}
|
||||
if matches!(op, BinaryOp::CmpOp(..))
|
||||
&& let TyKind::Ref(mtbl, lt, _) = p_right.kind(Interner)
|
||||
{
|
||||
self.write_expr_adj(
|
||||
rhs,
|
||||
Box::new([Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), *mtbl)),
|
||||
target: p_right.clone(),
|
||||
}]),
|
||||
);
|
||||
}
|
||||
sig.ret().clone()
|
||||
}
|
||||
|
|
@ -1664,14 +1663,12 @@ impl InferenceContext<'_> {
|
|||
Some((ty, field_id, adjustments, is_public)) => {
|
||||
self.write_expr_adj(receiver, adjustments.into_boxed_slice());
|
||||
self.result.field_resolutions.insert(tgt_expr, field_id);
|
||||
if !is_public {
|
||||
if let Either::Left(field) = field_id {
|
||||
// FIXME: Merge this diagnostic into UnresolvedField?
|
||||
self.push_diagnostic(InferenceDiagnostic::PrivateField {
|
||||
expr: tgt_expr,
|
||||
field,
|
||||
});
|
||||
}
|
||||
if !is_public && let Either::Left(field) = field_id {
|
||||
// FIXME: Merge this diagnostic into UnresolvedField?
|
||||
self.push_diagnostic(InferenceDiagnostic::PrivateField {
|
||||
expr: tgt_expr,
|
||||
field,
|
||||
});
|
||||
}
|
||||
ty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,53 +124,41 @@ impl InferenceContext<'_> {
|
|||
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
|
||||
}
|
||||
&Expr::Index { base, index } => {
|
||||
if mutability == Mutability::Mut {
|
||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
||||
if let Some(index_trait) =
|
||||
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
|
||||
{
|
||||
if let Some(index_fn) = index_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::index_mut))
|
||||
{
|
||||
*f = index_fn;
|
||||
let mut base_ty = None;
|
||||
let base_adjustments = self
|
||||
.result
|
||||
.expr_adjustments
|
||||
.get_mut(&base)
|
||||
.and_then(|it| it.last_mut());
|
||||
if let Some(Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
|
||||
target,
|
||||
}) = base_adjustments
|
||||
{
|
||||
if let TyKind::Ref(_, _, ty) = target.kind(Interner) {
|
||||
base_ty = Some(ty.clone());
|
||||
}
|
||||
*mutability = Mutability::Mut;
|
||||
}
|
||||
|
||||
// Apply `IndexMut` obligation for non-assignee expr
|
||||
if let Some(base_ty) = base_ty {
|
||||
let index_ty =
|
||||
if let Some(ty) = self.result.type_of_expr.get(index) {
|
||||
ty.clone()
|
||||
} else {
|
||||
self.infer_expr(
|
||||
index,
|
||||
&Expectation::none(),
|
||||
ExprIsRead::Yes,
|
||||
)
|
||||
};
|
||||
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
|
||||
.push(base_ty)
|
||||
.fill(|_| index_ty.clone().cast(Interner))
|
||||
.build();
|
||||
self.push_obligation(trait_ref.cast(Interner));
|
||||
}
|
||||
}
|
||||
if mutability == Mutability::Mut
|
||||
&& let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr)
|
||||
&& let Some(index_trait) =
|
||||
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
|
||||
&& let Some(index_fn) = index_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::index_mut))
|
||||
{
|
||||
*f = index_fn;
|
||||
let mut base_ty = None;
|
||||
let base_adjustments =
|
||||
self.result.expr_adjustments.get_mut(&base).and_then(|it| it.last_mut());
|
||||
if let Some(Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
|
||||
target,
|
||||
}) = base_adjustments
|
||||
{
|
||||
if let TyKind::Ref(_, _, ty) = target.kind(Interner) {
|
||||
base_ty = Some(ty.clone());
|
||||
}
|
||||
*mutability = Mutability::Mut;
|
||||
}
|
||||
|
||||
// Apply `IndexMut` obligation for non-assignee expr
|
||||
if let Some(base_ty) = base_ty {
|
||||
let index_ty = if let Some(ty) = self.result.type_of_expr.get(index) {
|
||||
ty.clone()
|
||||
} else {
|
||||
self.infer_expr(index, &Expectation::none(), ExprIsRead::Yes)
|
||||
};
|
||||
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
|
||||
.push(base_ty)
|
||||
.fill(|_| index_ty.clone().cast(Interner))
|
||||
.build();
|
||||
self.push_obligation(trait_ref.cast(Interner));
|
||||
}
|
||||
}
|
||||
self.infer_mut_expr(base, mutability);
|
||||
|
|
@ -178,28 +166,23 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
|
||||
let mut mutability = mutability;
|
||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
||||
if mutability == Mutability::Mut {
|
||||
if let Some(deref_trait) =
|
||||
LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate)
|
||||
{
|
||||
let ty = self.result.type_of_expr.get(*expr);
|
||||
let is_mut_ptr = ty.is_some_and(|ty| {
|
||||
let ty = self.table.resolve_ty_shallow(ty);
|
||||
matches!(
|
||||
ty.kind(Interner),
|
||||
chalk_ir::TyKind::Raw(Mutability::Mut, _)
|
||||
)
|
||||
});
|
||||
if is_mut_ptr {
|
||||
mutability = Mutability::Not;
|
||||
} else if let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||
{
|
||||
*f = deref_fn;
|
||||
}
|
||||
}
|
||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr)
|
||||
&& mutability == Mutability::Mut
|
||||
&& let Some(deref_trait) =
|
||||
LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate)
|
||||
{
|
||||
let ty = self.result.type_of_expr.get(*expr);
|
||||
let is_mut_ptr = ty.is_some_and(|ty| {
|
||||
let ty = self.table.resolve_ty_shallow(ty);
|
||||
matches!(ty.kind(Interner), chalk_ir::TyKind::Raw(Mutability::Mut, _))
|
||||
});
|
||||
if is_mut_ptr {
|
||||
mutability = Mutability::Not;
|
||||
} else if let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||
{
|
||||
*f = deref_fn;
|
||||
}
|
||||
}
|
||||
self.infer_mut_expr(*expr, mutability);
|
||||
|
|
|
|||
|
|
@ -498,12 +498,12 @@ impl InferenceContext<'_> {
|
|||
|
||||
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
|
||||
// allows it. See issue #16609
|
||||
if self.pat_is_irrefutable(decl) && expected.is_ty_var() {
|
||||
if let Some(resolved_array_ty) =
|
||||
if self.pat_is_irrefutable(decl)
|
||||
&& expected.is_ty_var()
|
||||
&& let Some(resolved_array_ty) =
|
||||
self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
|
||||
{
|
||||
self.unify(&expected, &resolved_array_ty);
|
||||
}
|
||||
{
|
||||
self.unify(&expected, &resolved_array_ty);
|
||||
}
|
||||
|
||||
let expected = self.resolve_ty_shallow(&expected);
|
||||
|
|
@ -539,17 +539,16 @@ impl InferenceContext<'_> {
|
|||
|
||||
fn infer_lit_pat(&mut self, expr: ExprId, expected: &Ty) -> Ty {
|
||||
// Like slice patterns, byte string patterns can denote both `&[u8; N]` and `&[u8]`.
|
||||
if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] {
|
||||
if let Some((inner, ..)) = expected.as_reference() {
|
||||
let inner = self.resolve_ty_shallow(inner);
|
||||
if matches!(inner.kind(Interner), TyKind::Slice(_)) {
|
||||
let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
|
||||
let slice_ty = TyKind::Slice(elem_ty).intern(Interner);
|
||||
let ty =
|
||||
TyKind::Ref(Mutability::Not, static_lifetime(), slice_ty).intern(Interner);
|
||||
self.write_expr_ty(expr, ty.clone());
|
||||
return ty;
|
||||
}
|
||||
if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
|
||||
&& let Some((inner, ..)) = expected.as_reference()
|
||||
{
|
||||
let inner = self.resolve_ty_shallow(inner);
|
||||
if matches!(inner.kind(Interner), TyKind::Slice(_)) {
|
||||
let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
|
||||
let slice_ty = TyKind::Slice(elem_ty).intern(Interner);
|
||||
let ty = TyKind::Ref(Mutability::Not, static_lifetime(), slice_ty).intern(Interner);
|
||||
self.write_expr_ty(expr, ty.clone());
|
||||
return ty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -830,10 +830,10 @@ fn named_associated_type_shorthand_candidates<R>(
|
|||
let data = t.hir_trait_id().trait_items(db);
|
||||
|
||||
for (name, assoc_id) in &data.items {
|
||||
if let AssocItemId::TypeAliasId(alias) = assoc_id {
|
||||
if let Some(result) = cb(name, &t, *alias) {
|
||||
return Some(result);
|
||||
}
|
||||
if let AssocItemId::TypeAliasId(alias) = assoc_id
|
||||
&& let Some(result) = cb(name, &t, *alias)
|
||||
{
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
|||
|
|
@ -360,15 +360,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(enum_segment) = enum_segment {
|
||||
if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
{
|
||||
self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
|
||||
segment: (enum_segment + 1) as u32,
|
||||
reason: GenericArgsProhibitedReason::EnumVariant,
|
||||
});
|
||||
}
|
||||
if let Some(enum_segment) = enum_segment
|
||||
&& segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
{
|
||||
self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
|
||||
segment: (enum_segment + 1) as u32,
|
||||
reason: GenericArgsProhibitedReason::EnumVariant,
|
||||
});
|
||||
}
|
||||
|
||||
self.handle_type_ns_resolution(&resolution);
|
||||
|
|
@ -417,15 +416,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(enum_segment) = enum_segment {
|
||||
if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
{
|
||||
self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
|
||||
segment: (enum_segment + 1) as u32,
|
||||
reason: GenericArgsProhibitedReason::EnumVariant,
|
||||
});
|
||||
}
|
||||
if let Some(enum_segment) = enum_segment
|
||||
&& segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
|
||||
{
|
||||
self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
|
||||
segment: (enum_segment + 1) as u32,
|
||||
reason: GenericArgsProhibitedReason::EnumVariant,
|
||||
});
|
||||
}
|
||||
|
||||
match &res {
|
||||
|
|
@ -576,13 +574,12 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
|||
// This simplifies the code a bit.
|
||||
let penultimate_idx = self.current_segment_idx.wrapping_sub(1);
|
||||
let penultimate = self.segments.get(penultimate_idx);
|
||||
if let Some(penultimate) = penultimate {
|
||||
if self.current_or_prev_segment.args_and_bindings.is_none()
|
||||
&& penultimate.args_and_bindings.is_some()
|
||||
{
|
||||
self.current_segment_idx = penultimate_idx;
|
||||
self.current_or_prev_segment = penultimate;
|
||||
}
|
||||
if let Some(penultimate) = penultimate
|
||||
&& self.current_or_prev_segment.args_and_bindings.is_none()
|
||||
&& penultimate.args_and_bindings.is_some()
|
||||
{
|
||||
self.current_segment_idx = penultimate_idx;
|
||||
self.current_or_prev_segment = penultimate;
|
||||
}
|
||||
var.lookup(self.ctx.db).parent.into()
|
||||
}
|
||||
|
|
@ -607,37 +604,36 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
|||
) -> Substitution {
|
||||
let mut lifetime_elision = self.ctx.lifetime_elision.clone();
|
||||
|
||||
if let Some(args) = self.current_or_prev_segment.args_and_bindings {
|
||||
if args.parenthesized != GenericArgsParentheses::No {
|
||||
let prohibit_parens = match def {
|
||||
GenericDefId::TraitId(trait_) => {
|
||||
// RTN is prohibited anyways if we got here.
|
||||
let is_rtn =
|
||||
args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
|
||||
let is_fn_trait = self
|
||||
.ctx
|
||||
.db
|
||||
.trait_signature(trait_)
|
||||
.flags
|
||||
.contains(TraitFlags::RUSTC_PAREN_SUGAR);
|
||||
is_rtn || !is_fn_trait
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if prohibit_parens {
|
||||
let segment = self.current_segment_u32();
|
||||
self.on_diagnostic(
|
||||
PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
|
||||
);
|
||||
|
||||
return TyBuilder::unknown_subst(self.ctx.db, def);
|
||||
if let Some(args) = self.current_or_prev_segment.args_and_bindings
|
||||
&& args.parenthesized != GenericArgsParentheses::No
|
||||
{
|
||||
let prohibit_parens = match def {
|
||||
GenericDefId::TraitId(trait_) => {
|
||||
// RTN is prohibited anyways if we got here.
|
||||
let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
|
||||
let is_fn_trait = self
|
||||
.ctx
|
||||
.db
|
||||
.trait_signature(trait_)
|
||||
.flags
|
||||
.contains(TraitFlags::RUSTC_PAREN_SUGAR);
|
||||
is_rtn || !is_fn_trait
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
|
||||
lifetime_elision =
|
||||
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
|
||||
if prohibit_parens {
|
||||
let segment = self.current_segment_u32();
|
||||
self.on_diagnostic(
|
||||
PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
|
||||
);
|
||||
|
||||
return TyBuilder::unknown_subst(self.ctx.db, def);
|
||||
}
|
||||
|
||||
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
|
||||
lifetime_elision =
|
||||
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
|
||||
}
|
||||
|
||||
self.substs_from_args_and_bindings(
|
||||
|
|
@ -753,18 +749,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
|
|||
match param {
|
||||
GenericParamDataRef::LifetimeParamData(_) => error_lifetime().cast(Interner),
|
||||
GenericParamDataRef::TypeParamData(param) => {
|
||||
if !infer_args && param.default.is_some() {
|
||||
if let Some(default) = default() {
|
||||
return default;
|
||||
}
|
||||
if !infer_args
|
||||
&& param.default.is_some()
|
||||
&& let Some(default) = default()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
TyKind::Error.intern(Interner).cast(Interner)
|
||||
}
|
||||
GenericParamDataRef::ConstParamData(param) => {
|
||||
if !infer_args && param.default.is_some() {
|
||||
if let Some(default) = default() {
|
||||
return default;
|
||||
}
|
||||
if !infer_args
|
||||
&& param.default.is_some()
|
||||
&& let Some(default) = default()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
let GenericParamId::ConstParamId(const_id) = param_id else {
|
||||
unreachable!("non-const param ID for const param");
|
||||
|
|
|
|||
|
|
@ -581,15 +581,15 @@ impl ReceiverAdjustments {
|
|||
}
|
||||
if self.unsize_array {
|
||||
ty = 'it: {
|
||||
if let TyKind::Ref(m, l, inner) = ty.kind(Interner) {
|
||||
if let TyKind::Array(inner, _) = inner.kind(Interner) {
|
||||
break 'it TyKind::Ref(
|
||||
*m,
|
||||
l.clone(),
|
||||
TyKind::Slice(inner.clone()).intern(Interner),
|
||||
)
|
||||
.intern(Interner);
|
||||
}
|
||||
if let TyKind::Ref(m, l, inner) = ty.kind(Interner)
|
||||
&& let TyKind::Array(inner, _) = inner.kind(Interner)
|
||||
{
|
||||
break 'it TyKind::Ref(
|
||||
*m,
|
||||
l.clone(),
|
||||
TyKind::Slice(inner.clone()).intern(Interner),
|
||||
)
|
||||
.intern(Interner);
|
||||
}
|
||||
// FIXME: report diagnostic if array unsizing happens without indirection.
|
||||
ty
|
||||
|
|
@ -1549,11 +1549,11 @@ fn is_valid_impl_method_candidate(
|
|||
check_that!(receiver_ty.is_none());
|
||||
check_that!(name.is_none_or(|n| n == item_name));
|
||||
|
||||
if let Some(from_module) = visible_from_module {
|
||||
if !db.assoc_visibility(c.into()).is_visible_from(db, from_module) {
|
||||
cov_mark::hit!(const_candidate_not_visible);
|
||||
return IsValidCandidate::NotVisible;
|
||||
}
|
||||
if let Some(from_module) = visible_from_module
|
||||
&& !db.assoc_visibility(c.into()).is_visible_from(db, from_module)
|
||||
{
|
||||
cov_mark::hit!(const_candidate_not_visible);
|
||||
return IsValidCandidate::NotVisible;
|
||||
}
|
||||
let self_ty_matches = table.run_in_snapshot(|table| {
|
||||
let expected_self_ty =
|
||||
|
|
@ -1638,11 +1638,11 @@ fn is_valid_impl_fn_candidate(
|
|||
let db = table.db;
|
||||
let data = db.function_signature(fn_id);
|
||||
|
||||
if let Some(from_module) = visible_from_module {
|
||||
if !db.assoc_visibility(fn_id.into()).is_visible_from(db, from_module) {
|
||||
cov_mark::hit!(autoderef_candidate_not_visible);
|
||||
return IsValidCandidate::NotVisible;
|
||||
}
|
||||
if let Some(from_module) = visible_from_module
|
||||
&& !db.assoc_visibility(fn_id.into()).is_visible_from(db, from_module)
|
||||
{
|
||||
cov_mark::hit!(autoderef_candidate_not_visible);
|
||||
return IsValidCandidate::NotVisible;
|
||||
}
|
||||
table.run_in_snapshot(|table| {
|
||||
let _p = tracing::info_span!("subst_for_def").entered();
|
||||
|
|
|
|||
|
|
@ -559,10 +559,9 @@ fn mutability_of_locals(
|
|||
},
|
||||
p,
|
||||
) = value
|
||||
&& place_case(db, body, p) != ProjectionCase::Indirect
|
||||
{
|
||||
if place_case(db, body, p) != ProjectionCase::Indirect {
|
||||
push_mut_span(p.local, statement.span, &mut result);
|
||||
}
|
||||
push_mut_span(p.local, statement.span, &mut result);
|
||||
}
|
||||
}
|
||||
StatementKind::FakeRead(p) => {
|
||||
|
|
|
|||
|
|
@ -1082,18 +1082,18 @@ impl Evaluator<'_> {
|
|||
let stack_size = {
|
||||
let mut stack_ptr = self.stack.len();
|
||||
for (id, it) in body.locals.iter() {
|
||||
if id == return_slot() {
|
||||
if let Some(destination) = destination {
|
||||
locals.ptr.insert(id, destination);
|
||||
continue;
|
||||
}
|
||||
if id == return_slot()
|
||||
&& let Some(destination) = destination
|
||||
{
|
||||
locals.ptr.insert(id, destination);
|
||||
continue;
|
||||
}
|
||||
let (size, align) = self.size_align_of_sized(
|
||||
&it.ty,
|
||||
&locals,
|
||||
"no unsized local in extending stack",
|
||||
)?;
|
||||
while stack_ptr % align != 0 {
|
||||
while !stack_ptr.is_multiple_of(align) {
|
||||
stack_ptr += 1;
|
||||
}
|
||||
let my_ptr = stack_ptr;
|
||||
|
|
@ -1673,14 +1673,14 @@ impl Evaluator<'_> {
|
|||
if let Some(it) = goal(kind) {
|
||||
return Ok(it);
|
||||
}
|
||||
if let TyKind::Adt(id, subst) = kind {
|
||||
if let AdtId::StructId(struct_id) = id.0 {
|
||||
let field_types = self.db.field_types(struct_id.into());
|
||||
if let Some(ty) =
|
||||
field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst))
|
||||
{
|
||||
return self.coerce_unsized_look_through_fields(&ty, goal);
|
||||
}
|
||||
if let TyKind::Adt(id, subst) = kind
|
||||
&& let AdtId::StructId(struct_id) = id.0
|
||||
{
|
||||
let field_types = self.db.field_types(struct_id.into());
|
||||
if let Some(ty) =
|
||||
field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst))
|
||||
{
|
||||
return self.coerce_unsized_look_through_fields(&ty, goal);
|
||||
}
|
||||
}
|
||||
Err(MirEvalError::CoerceUnsizedError(ty.clone()))
|
||||
|
|
@ -1778,17 +1778,15 @@ impl Evaluator<'_> {
|
|||
locals: &Locals,
|
||||
) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
|
||||
let adt = it.adt_id(self.db);
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||
if let VariantId::EnumVariantId(it) = it {
|
||||
if let AdtId::EnumId(e) = adt {
|
||||
if f.lookup(self.db).parent == e {
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy layout
|
||||
let i = self.const_eval_discriminant(it)?;
|
||||
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner
|
||||
&& let VariantId::EnumVariantId(it) = it
|
||||
&& let AdtId::EnumId(e) = adt
|
||||
&& f.lookup(self.db).parent == e
|
||||
{
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy layout
|
||||
let i = self.const_eval_discriminant(it)?;
|
||||
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
|
||||
}
|
||||
let layout = self.layout_adt(adt, subst)?;
|
||||
Ok(match &layout.variants {
|
||||
|
|
@ -1909,10 +1907,10 @@ impl Evaluator<'_> {
|
|||
let name = const_id.name(self.db);
|
||||
MirEvalError::ConstEvalError(name, Box::new(e))
|
||||
})?;
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value {
|
||||
if let ConstScalar::Bytes(v, mm) = &c.interned {
|
||||
break 'b (v, mm);
|
||||
}
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value
|
||||
&& let ConstScalar::Bytes(v, mm) = &c.interned
|
||||
{
|
||||
break 'b (v, mm);
|
||||
}
|
||||
not_supported!("unevaluatable constant");
|
||||
}
|
||||
|
|
@ -2055,14 +2053,13 @@ impl Evaluator<'_> {
|
|||
.is_sized()
|
||||
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||
if let Some((AdtId::EnumId(e), _)) = ty.as_adt() {
|
||||
if f.lookup(self.db).parent == e {
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy size
|
||||
return Ok(Some((16, 16)));
|
||||
}
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner
|
||||
&& let Some((AdtId::EnumId(e), _)) = ty.as_adt()
|
||||
&& f.lookup(self.db).parent == e
|
||||
{
|
||||
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
|
||||
// infinite sized type errors) we use a dummy size
|
||||
return Ok(Some((16, 16)));
|
||||
}
|
||||
let layout = self.layout(ty);
|
||||
if self.assert_placeholder_ty_is_unused
|
||||
|
|
@ -2103,7 +2100,7 @@ impl Evaluator<'_> {
|
|||
if !align.is_power_of_two() || align > 10000 {
|
||||
return Err(MirEvalError::UndefinedBehavior(format!("Alignment {align} is invalid")));
|
||||
}
|
||||
while self.heap.len() % align != 0 {
|
||||
while !self.heap.len().is_multiple_of(align) {
|
||||
self.heap.push(0);
|
||||
}
|
||||
if size.checked_add(self.heap.len()).is_none_or(|x| x > self.memory_limit) {
|
||||
|
|
|
|||
|
|
@ -119,25 +119,25 @@ impl Evaluator<'_> {
|
|||
destination.write_from_bytes(self, &result)?;
|
||||
return Ok(true);
|
||||
}
|
||||
if let ItemContainerId::TraitId(t) = def.lookup(self.db).container {
|
||||
if self.db.lang_attr(t.into()) == Some(LangItem::Clone) {
|
||||
let [self_ty] = generic_args.as_slice(Interner) else {
|
||||
not_supported!("wrong generic arg count for clone");
|
||||
};
|
||||
let Some(self_ty) = self_ty.ty(Interner) else {
|
||||
not_supported!("wrong generic arg kind for clone");
|
||||
};
|
||||
// Clone has special impls for tuples and function pointers
|
||||
if matches!(
|
||||
self_ty.kind(Interner),
|
||||
TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..)
|
||||
) {
|
||||
self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?;
|
||||
return Ok(true);
|
||||
}
|
||||
// Return early to prevent caching clone as non special fn.
|
||||
return Ok(false);
|
||||
if let ItemContainerId::TraitId(t) = def.lookup(self.db).container
|
||||
&& self.db.lang_attr(t.into()) == Some(LangItem::Clone)
|
||||
{
|
||||
let [self_ty] = generic_args.as_slice(Interner) else {
|
||||
not_supported!("wrong generic arg count for clone");
|
||||
};
|
||||
let Some(self_ty) = self_ty.ty(Interner) else {
|
||||
not_supported!("wrong generic arg kind for clone");
|
||||
};
|
||||
// Clone has special impls for tuples and function pointers
|
||||
if matches!(
|
||||
self_ty.kind(Interner),
|
||||
TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..)
|
||||
) {
|
||||
self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?;
|
||||
return Ok(true);
|
||||
}
|
||||
// Return early to prevent caching clone as non special fn.
|
||||
return Ok(false);
|
||||
}
|
||||
self.not_special_fn_cache.borrow_mut().insert(def);
|
||||
Ok(false)
|
||||
|
|
@ -1256,23 +1256,22 @@ impl Evaluator<'_> {
|
|||
let addr = tuple.interval.addr.offset(offset);
|
||||
args.push(IntervalAndTy::new(addr, field, self, locals)?);
|
||||
}
|
||||
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
|
||||
if let Some(def) = target
|
||||
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id)
|
||||
&& let Some(def) = target
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::call_once))
|
||||
{
|
||||
self.exec_fn_trait(
|
||||
def,
|
||||
&args,
|
||||
// FIXME: wrong for manual impls of `FnOnce`
|
||||
Substitution::empty(Interner),
|
||||
locals,
|
||||
destination,
|
||||
None,
|
||||
span,
|
||||
)?;
|
||||
return Ok(true);
|
||||
}
|
||||
{
|
||||
self.exec_fn_trait(
|
||||
def,
|
||||
&args,
|
||||
// FIXME: wrong for manual impls of `FnOnce`
|
||||
Substitution::empty(Interner),
|
||||
locals,
|
||||
destination,
|
||||
None,
|
||||
span,
|
||||
)?;
|
||||
return Ok(true);
|
||||
}
|
||||
not_supported!("FnOnce was not available for executing const_eval_select");
|
||||
}
|
||||
|
|
@ -1367,12 +1366,11 @@ impl Evaluator<'_> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if signed {
|
||||
if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() {
|
||||
if l != r {
|
||||
result = (l as i8).cmp(&(r as i8));
|
||||
}
|
||||
}
|
||||
if signed
|
||||
&& let Some((&l, &r)) = lhs.iter().zip(rhs).next_back()
|
||||
&& l != r
|
||||
{
|
||||
result = (l as i8).cmp(&(r as i8));
|
||||
}
|
||||
if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
|
||||
let ty = self.db.ty(e.into());
|
||||
|
|
|
|||
|
|
@ -114,12 +114,11 @@ impl Evaluator<'_> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if is_signed {
|
||||
if let Some((&l, &r)) = l.iter().zip(r).next_back() {
|
||||
if l != r {
|
||||
result = (l as i8).cmp(&(r as i8));
|
||||
}
|
||||
}
|
||||
if is_signed
|
||||
&& let Some((&l, &r)) = l.iter().zip(r).next_back()
|
||||
&& l != r
|
||||
{
|
||||
result = (l as i8).cmp(&(r as i8));
|
||||
}
|
||||
let result = match result {
|
||||
Ordering::Less => ["lt", "le", "ne"].contains(&name),
|
||||
|
|
|
|||
|
|
@ -320,11 +320,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
expr_id: ExprId,
|
||||
current: BasicBlockId,
|
||||
) -> Result<Option<(Operand, BasicBlockId)>> {
|
||||
if !self.has_adjustments(expr_id) {
|
||||
if let Expr::Literal(l) = &self.body[expr_id] {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
return Ok(Some((self.lower_literal_to_operand(ty, l)?, current)));
|
||||
}
|
||||
if !self.has_adjustments(expr_id)
|
||||
&& let Expr::Literal(l) = &self.body[expr_id]
|
||||
{
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
return Ok(Some((self.lower_literal_to_operand(ty, l)?, current)));
|
||||
}
|
||||
let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else {
|
||||
return Ok(None);
|
||||
|
|
@ -1039,18 +1039,18 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
&& rhs_ty.is_scalar()
|
||||
&& (lhs_ty == rhs_ty || builtin_inequal_impls)
|
||||
};
|
||||
if !is_builtin {
|
||||
if let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id) {
|
||||
let func = Operand::from_fn(self.db, func_id, generic_args);
|
||||
return self.lower_call_and_args(
|
||||
func,
|
||||
[*lhs, *rhs].into_iter(),
|
||||
place,
|
||||
current,
|
||||
self.is_uninhabited(expr_id),
|
||||
expr_id.into(),
|
||||
);
|
||||
}
|
||||
if !is_builtin
|
||||
&& let Some((func_id, generic_args)) = self.infer.method_resolution(expr_id)
|
||||
{
|
||||
let func = Operand::from_fn(self.db, func_id, generic_args);
|
||||
return self.lower_call_and_args(
|
||||
func,
|
||||
[*lhs, *rhs].into_iter(),
|
||||
place,
|
||||
current,
|
||||
self.is_uninhabited(expr_id),
|
||||
expr_id.into(),
|
||||
);
|
||||
}
|
||||
if let hir_def::hir::BinaryOp::Assignment { op: Some(op) } = op {
|
||||
// last adjustment is `&mut` which we don't want it.
|
||||
|
|
@ -1596,10 +1596,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
|
||||
fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty {
|
||||
let mut ty = None;
|
||||
if let Some(it) = self.infer.expr_adjustments.get(&e) {
|
||||
if let Some(it) = it.last() {
|
||||
ty = Some(it.target.clone());
|
||||
}
|
||||
if let Some(it) = self.infer.expr_adjustments.get(&e)
|
||||
&& let Some(it) = it.last()
|
||||
{
|
||||
ty = Some(it.target.clone());
|
||||
}
|
||||
ty.unwrap_or_else(|| self.expr_ty_without_adjust(e))
|
||||
}
|
||||
|
|
@ -1848,13 +1848,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
self.result.param_locals.extend(params.clone().map(|(it, ty)| {
|
||||
let local_id = self.result.locals.alloc(Local { ty });
|
||||
self.drop_scopes.last_mut().unwrap().locals.push(local_id);
|
||||
if let Pat::Bind { id, subpat: None } = self.body[it] {
|
||||
if matches!(
|
||||
if let Pat::Bind { id, subpat: None } = self.body[it]
|
||||
&& matches!(
|
||||
self.body[id].mode,
|
||||
BindingAnnotation::Unannotated | BindingAnnotation::Mutable
|
||||
) {
|
||||
self.result.binding_locals.insert(id, local_id);
|
||||
}
|
||||
)
|
||||
{
|
||||
self.result.binding_locals.insert(id, local_id);
|
||||
}
|
||||
local_id
|
||||
}));
|
||||
|
|
@ -1887,10 +1887,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
.into_iter()
|
||||
.skip(base_param_count + self_binding.is_some() as usize);
|
||||
for ((param, _), local) in params.zip(local_params) {
|
||||
if let Pat::Bind { id, .. } = self.body[param] {
|
||||
if local == self.binding_local(id)? {
|
||||
continue;
|
||||
}
|
||||
if let Pat::Bind { id, .. } = self.body[param]
|
||||
&& local == self.binding_local(id)?
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let r = self.pattern_match(current, None, local.into(), param)?;
|
||||
if let Some(b) = r.1 {
|
||||
|
|
|
|||
|
|
@ -189,17 +189,14 @@ impl MirLowerCtx<'_> {
|
|||
self.expr_ty_without_adjust(expr_id),
|
||||
expr_id.into(),
|
||||
'b: {
|
||||
if let Some((f, _)) = self.infer.method_resolution(expr_id) {
|
||||
if let Some(deref_trait) =
|
||||
if let Some((f, _)) = self.infer.method_resolution(expr_id)
|
||||
&& let Some(deref_trait) =
|
||||
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
|
||||
{
|
||||
if let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
}
|
||||
&& let Some(deref_fn) = deref_trait
|
||||
.trait_items(self.db)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
false
|
||||
},
|
||||
|
|
|
|||
|
|
@ -317,27 +317,26 @@ impl MirLowerCtx<'_> {
|
|||
(current, current_else) =
|
||||
self.pattern_match_inner(current, current_else, next_place, pat, mode)?;
|
||||
}
|
||||
if let &Some(slice) = slice {
|
||||
if mode != MatchingMode::Check {
|
||||
if let Pat::Bind { id, subpat: _ } = self.body[slice] {
|
||||
let next_place = cond_place.project(
|
||||
ProjectionElem::Subslice {
|
||||
from: prefix.len() as u64,
|
||||
to: suffix.len() as u64,
|
||||
},
|
||||
&mut self.result.projection_store,
|
||||
);
|
||||
let mode = self.infer.binding_modes[slice];
|
||||
(current, current_else) = self.pattern_match_binding(
|
||||
id,
|
||||
mode,
|
||||
next_place,
|
||||
(slice).into(),
|
||||
current,
|
||||
current_else,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
if let &Some(slice) = slice
|
||||
&& mode != MatchingMode::Check
|
||||
&& let Pat::Bind { id, subpat: _ } = self.body[slice]
|
||||
{
|
||||
let next_place = cond_place.project(
|
||||
ProjectionElem::Subslice {
|
||||
from: prefix.len() as u64,
|
||||
to: suffix.len() as u64,
|
||||
},
|
||||
&mut self.result.projection_store,
|
||||
);
|
||||
let mode = self.infer.binding_modes[slice];
|
||||
(current, current_else) = self.pattern_match_binding(
|
||||
id,
|
||||
mode,
|
||||
next_place,
|
||||
(slice).into(),
|
||||
current,
|
||||
current_else,
|
||||
)?;
|
||||
}
|
||||
for (i, &pat) in suffix.iter().enumerate() {
|
||||
let next_place = cond_place.project(
|
||||
|
|
@ -391,10 +390,10 @@ impl MirLowerCtx<'_> {
|
|||
return Ok((current, current_else));
|
||||
}
|
||||
let (c, subst) = 'b: {
|
||||
if let Some(x) = self.infer.assoc_resolutions_for_pat(pattern) {
|
||||
if let AssocItemId::ConstId(c) = x.0 {
|
||||
break 'b (c, x.1);
|
||||
}
|
||||
if let Some(x) = self.infer.assoc_resolutions_for_pat(pattern)
|
||||
&& let AssocItemId::ConstId(c) = x.0
|
||||
{
|
||||
break 'b (c, x.1);
|
||||
}
|
||||
if let ResolveValueResult::ValueNs(ValueNs::ConstId(c), _) = pr {
|
||||
break 'b (c, Substitution::empty(Interner));
|
||||
|
|
|
|||
|
|
@ -125,11 +125,10 @@ pub(crate) fn trait_solve_query(
|
|||
alias: AliasTy::Projection(projection_ty),
|
||||
..
|
||||
}))) = &goal.value.goal.data(Interner)
|
||||
&& let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner)
|
||||
{
|
||||
if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner) {
|
||||
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
|
||||
return Some(Solution::Ambig(Guidance::Unknown));
|
||||
}
|
||||
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
|
||||
return Some(Solution::Ambig(Guidance::Unknown));
|
||||
}
|
||||
|
||||
// Chalk see `UnevaluatedConst` as a unique concrete value, but we see it as an alias for another const. So
|
||||
|
|
|
|||
|
|
@ -333,13 +333,13 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
|
|||
constant: Const,
|
||||
_outer_binder: DebruijnIndex,
|
||||
) -> Result<Const, Self::Error> {
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
|
||||
if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||
return Ok(eval);
|
||||
} else {
|
||||
return Ok(unknown_const(constant.data(Interner).ty.clone()));
|
||||
}
|
||||
if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value
|
||||
&& let ConstScalar::UnevaluatedConst(id, subst) = &c.interned
|
||||
{
|
||||
if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
|
||||
return Ok(eval);
|
||||
} else {
|
||||
return Ok(unknown_const(constant.data(Interner).ty.clone()));
|
||||
}
|
||||
}
|
||||
Ok(constant)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue