2024-02-11 09:22:52 +01:00
|
|
|
//! HIR ty lowering: Lowers type-system entities[^1] from the [HIR][hir] to
|
|
|
|
//! the [`rustc_middle::ty`] representation.
|
|
|
|
//!
|
|
|
|
//! Not to be confused with *AST lowering* which lowers AST constructs to HIR ones
|
|
|
|
//! or with *THIR* / *MIR* *lowering* / *building* which lowers HIR *bodies*
|
|
|
|
//! (i.e., “executable code”) to THIR / MIR.
|
|
|
|
//!
|
|
|
|
//! Most lowering routines are defined on [`dyn HirTyLowerer`](HirTyLowerer) directly,
|
|
|
|
//! like the main routine of this module, `lower_ty`.
|
|
|
|
//!
|
|
|
|
//! This module used to be called `astconv`.
|
|
|
|
//!
|
|
|
|
//! [^1]: This includes types, lifetimes / regions, constants in type positions,
|
|
|
|
//! trait references and bounds.
|
2014-11-26 04:52:02 -05:00
|
|
|
|
2023-06-16 18:24:43 +00:00
|
|
|
mod bounds;
|
2024-03-22 14:20:31 +08:00
|
|
|
pub mod errors;
|
2023-01-11 19:07:03 +00:00
|
|
|
pub mod generics;
|
2023-06-16 16:54:51 +00:00
|
|
|
mod lint;
|
2023-06-05 17:47:41 +00:00
|
|
|
mod object_safety;
|
2020-01-13 20:30:35 -08:00
|
|
|
|
2020-08-19 19:07:03 +02:00
|
|
|
use crate::bounds::Bounds;
|
2022-01-05 11:43:21 +01:00
|
|
|
use crate::collect::HirPlaceholderCollector;
|
2023-01-31 12:23:26 +00:00
|
|
|
use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
|
2024-05-27 23:53:46 +02:00
|
|
|
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
|
2024-02-11 11:09:25 +01:00
|
|
|
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
|
2023-02-06 18:38:52 +00:00
|
|
|
use crate::middle::resolve_bound_vars as rbv;
|
2019-12-24 17:38:22 -05:00
|
|
|
use crate::require_c_abi_if_c_variadic;
|
2021-07-10 10:00:54 +02:00
|
|
|
use rustc_ast::TraitObjectSyntax;
|
2024-02-11 19:50:50 +08:00
|
|
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
2022-01-23 12:34:26 -06:00
|
|
|
use rustc_errors::{
|
2024-03-22 14:20:31 +08:00
|
|
|
codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, FatalError,
|
2022-01-23 12:34:26 -06:00
|
|
|
};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir as hir;
|
2020-02-11 10:41:28 -08:00
|
|
|
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
2020-04-12 13:45:41 +01:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
2020-03-23 22:39:59 +01:00
|
|
|
use rustc_hir::intravisit::{walk_generics, Visitor as _};
|
2024-03-06 17:24:13 +11:00
|
|
|
use rustc_hir::{GenericArg, GenericArgs, HirId};
|
2023-11-25 17:48:09 -03:00
|
|
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
2022-12-08 13:31:21 +01:00
|
|
|
use rustc_infer::traits::ObligationCause;
|
2022-06-04 17:05:33 -05:00
|
|
|
use rustc_middle::middle::stability::AllowUnstable;
|
2023-02-02 13:57:36 +00:00
|
|
|
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
2024-05-20 12:57:07 -04:00
|
|
|
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
|
2023-07-11 22:35:29 +01:00
|
|
|
use rustc_middle::ty::{
|
2024-02-01 08:18:55 +00:00
|
|
|
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
|
|
|
|
TypeVisitableExt,
|
2023-07-11 22:35:29 +01:00
|
|
|
};
|
2024-05-08 16:40:46 +10:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2023-06-16 16:54:51 +00:00
|
|
|
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
2023-02-19 04:03:56 +00:00
|
|
|
use rustc_span::edit_distance::find_best_match_for_name;
|
2022-05-27 19:53:31 -07:00
|
|
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
2024-03-22 14:20:31 +08:00
|
|
|
use rustc_span::{sym, Span, DUMMY_SP};
|
2018-04-25 19:30:39 +03:00
|
|
|
use rustc_target::spec::abi;
|
2020-02-11 21:19:40 +01:00
|
|
|
use rustc_trait_selection::traits::wf::object_region_bounds;
|
2023-11-25 17:48:09 -03:00
|
|
|
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
2018-11-27 02:59:49 +00:00
|
|
|
|
2023-02-26 23:51:49 +00:00
|
|
|
use std::fmt::Display;
|
2018-11-27 02:59:49 +00:00
|
|
|
use std::slice;
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// A path segment that is semantically allowed to have generic arguments.
|
2018-12-18 18:59:00 +00:00
|
|
|
#[derive(Debug)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub struct GenericPathSegment(pub DefId, pub usize);
|
2018-12-03 21:50:49 +00:00
|
|
|
|
2023-04-18 23:55:05 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct OnlySelfBounds(pub bool);
|
|
|
|
|
2023-06-15 01:04:37 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub enum PredicateFilter {
|
|
|
|
/// All predicates may be implied by the trait.
|
|
|
|
All,
|
|
|
|
|
|
|
|
/// Only traits that reference `Self: ..` are implied by the trait.
|
|
|
|
SelfOnly,
|
|
|
|
|
|
|
|
/// Only traits that reference `Self: ..` and define an associated type
|
|
|
|
/// with the given ident are implied by the trait.
|
|
|
|
SelfThatDefines(Ident),
|
|
|
|
|
|
|
|
/// Only traits that reference `Self: ..` and their associated type bounds.
|
|
|
|
/// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
|
|
|
|
/// and `<Self as Tr>::A: B`.
|
|
|
|
SelfAndAssociatedTypeBounds,
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// A context which can lower type-system entities from the [HIR][hir] to
|
|
|
|
/// the [`rustc_middle::ty`] representation.
|
|
|
|
///
|
|
|
|
/// This trait used to be called `AstConv`.
|
2024-03-15 03:21:55 +01:00
|
|
|
pub trait HirTyLowerer<'tcx> {
|
2023-01-22 05:11:24 +00:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx>;
|
2015-01-04 06:10:34 -05:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Returns the [`DefId`] of the overarching item whose constituents get lowered.
|
2022-10-31 16:19:36 +00:00
|
|
|
fn item_def_id(&self) -> DefId;
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2024-03-22 05:47:11 +01:00
|
|
|
/// Returns `true` if the current context allows the use of inference variables.
|
|
|
|
fn allow_infer(&self) -> bool;
|
|
|
|
|
|
|
|
/// Returns the region to use when a lifetime is omitted (and not elided).
|
|
|
|
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
|
|
|
|
-> Option<ty::Region<'tcx>>;
|
|
|
|
|
|
|
|
/// Returns the type to use when a type is omitted.
|
|
|
|
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
|
|
|
|
|
|
|
|
/// Returns the const to use when a const is omitted.
|
|
|
|
fn ct_infer(
|
|
|
|
&self,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
param: Option<&ty::GenericParamDef>,
|
|
|
|
span: Span,
|
|
|
|
) -> Const<'tcx>;
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Probe bounds in scope where the bounded type coincides with the given type parameter.
|
|
|
|
///
|
|
|
|
/// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter
|
|
|
|
/// with the given `def_id`. This is a subset of the full set of bounds.
|
|
|
|
///
|
|
|
|
/// This method may use the given `assoc_name` to disregard bounds whose trait reference
|
|
|
|
/// doesn't define an associated item with the provided name.
|
2019-07-12 06:29:27 -04:00
|
|
|
///
|
2024-02-11 09:22:52 +01:00
|
|
|
/// This is used for one specific purpose: Resolving “short-hand” associated type references
|
|
|
|
/// like `T::Item` where `T` is a type parameter. In principle, we would do that by first
|
|
|
|
/// getting the full set of predicates in scope and then filtering down to find those that
|
|
|
|
/// apply to `T`, but this can lead to cycle errors. The problem is that we have to do this
|
|
|
|
/// resolution *in order to create the predicates in the first place*.
|
|
|
|
/// Hence, we have this “special pass”.
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_ty_param_bounds(
|
2020-12-03 20:10:55 -03:00
|
|
|
&self,
|
|
|
|
span: Span,
|
2023-03-13 19:06:41 +00:00
|
|
|
def_id: LocalDefId,
|
2020-12-03 20:10:55 -03:00
|
|
|
assoc_name: Ident,
|
|
|
|
) -> ty::GenericPredicates<'tcx>;
|
2015-02-17 11:04:25 -05:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower an associated type to a projection.
|
|
|
|
///
|
|
|
|
/// This method has to be defined by the concrete lowering context because
|
|
|
|
/// dealing with higher-ranked trait references depends on its capabilities:
|
|
|
|
///
|
|
|
|
/// If the context can make use of type inference, it can simply instantiate
|
|
|
|
/// any late-bound vars bound by the trait reference with inference variables.
|
|
|
|
/// If it doesn't support type inference, there is nothing reasonable it can
|
|
|
|
/// do except reject the associated type.
|
|
|
|
///
|
|
|
|
/// The canonical example of this is associated type `T::P` where `T` is a type
|
|
|
|
/// param constrained by `T: for<'a> Trait<'a>` and where `Trait` defines `P`.
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_assoc_ty(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
item_def_id: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
item_segment: &hir::PathSegment<'tcx>,
|
2019-12-24 17:38:22 -05:00
|
|
|
poly_trait_ref: ty::PolyTraitRef<'tcx>,
|
|
|
|
) -> Ty<'tcx>;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2022-10-29 16:19:57 +03:00
|
|
|
/// Returns `AdtDef` if `ty` is an ADT.
|
2024-02-11 09:22:52 +01:00
|
|
|
///
|
|
|
|
/// Note that `ty` might be a alias type that needs normalization.
|
2022-10-29 16:19:57 +03:00
|
|
|
/// This used to get the enum variants in scope of the type.
|
|
|
|
/// For example, `Self::A` could refer to an associated type
|
|
|
|
/// or to an enum variant depending on the result of this function.
|
|
|
|
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
|
2016-03-15 04:49:10 -04:00
|
|
|
|
2024-03-22 05:47:11 +01:00
|
|
|
/// Record the lowered type of a HIR node in this context.
|
2024-03-06 17:24:13 +11:00
|
|
|
fn record_ty(&self, hir_id: HirId, ty: Ty<'tcx>, span: Span);
|
2024-03-22 05:47:11 +01:00
|
|
|
|
|
|
|
/// The inference context of the lowering context if applicable.
|
|
|
|
fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Taint the context with errors.
|
|
|
|
///
|
|
|
|
/// Invoke this when you encounter an error from some prior pass like name resolution.
|
|
|
|
/// This is used to help suppress derived errors typeck might otherwise report.
|
2022-11-18 11:30:21 +00:00
|
|
|
fn set_tainted_by_errors(&self, e: ErrorGuaranteed);
|
2017-09-16 02:33:41 +03:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Convenience method for coercing the lowering context into a trait object type.
|
|
|
|
///
|
|
|
|
/// Most lowering routines are defined on the trait object type directly
|
|
|
|
/// necessitating a coercion step from the concrete lowering context.
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lowerer(&self) -> &dyn HirTyLowerer<'tcx>
|
2023-01-11 18:58:44 +00:00
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
self
|
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
}
|
|
|
|
|
2020-05-21 19:51:39 +01:00
|
|
|
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
|
|
|
/// are present in a set of generic arguments.
|
|
|
|
///
|
|
|
|
/// For example if we have some method `fn f<'a>(&'a self)` implemented
|
|
|
|
/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
|
|
|
|
/// is late-bound so should not be provided explicitly. Thus, if `f` is
|
|
|
|
/// instantiated with some generic arguments providing `'a` explicitly,
|
|
|
|
/// we taint those arguments with `ExplicitLateBound::Yes` so that we
|
|
|
|
/// can provide an appropriate diagnostic later.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
2020-05-21 19:51:39 +01:00
|
|
|
pub enum ExplicitLateBound {
|
|
|
|
Yes,
|
|
|
|
No,
|
|
|
|
}
|
|
|
|
|
2021-01-02 19:45:11 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
|
|
|
pub enum IsMethodCall {
|
|
|
|
Yes,
|
|
|
|
No,
|
|
|
|
}
|
|
|
|
|
2020-08-19 19:07:03 +02:00
|
|
|
/// Denotes the "position" of a generic argument, indicating if it is a generic type,
|
|
|
|
/// generic function or generic method call.
|
2020-05-21 19:51:39 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2020-08-19 19:07:03 +02:00
|
|
|
pub(crate) enum GenericArgPosition {
|
2018-08-20 12:52:56 +01:00
|
|
|
Type,
|
2018-11-27 02:59:49 +00:00
|
|
|
Value, // e.g., functions
|
2018-08-20 12:52:56 +01:00
|
|
|
MethodCall,
|
2018-08-08 01:46:00 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 00:41:33 +00:00
|
|
|
/// A marker denoting that the generic arguments that were
|
|
|
|
/// provided did not match the respective generic parameters.
|
2024-06-03 12:56:47 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2020-02-22 01:55:35 +00:00
|
|
|
pub struct GenericArgCountMismatch {
|
2024-06-03 12:56:47 +00:00
|
|
|
pub reported: ErrorGuaranteed,
|
2024-06-03 13:06:59 +00:00
|
|
|
/// A list of indices of arguments provided that were not valid.
|
|
|
|
pub invalid_args: Vec<usize>,
|
2020-02-22 01:55:35 +00:00
|
|
|
}
|
2020-01-23 00:41:33 +00:00
|
|
|
|
2020-05-21 19:51:39 +01:00
|
|
|
/// Decorates the result of a generic argument count mismatch
|
|
|
|
/// check with whether explicit late bounds were provided.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2020-05-21 19:51:39 +01:00
|
|
|
pub struct GenericArgCountResult {
|
|
|
|
pub explicit_late_bound: ExplicitLateBound,
|
|
|
|
pub correct: Result<(), GenericArgCountMismatch>,
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// A context which can lower HIR's [`GenericArg`] to `rustc_middle`'s [`ty::GenericArg`].
|
|
|
|
///
|
|
|
|
/// Its only consumer is [`generics::lower_generic_args`].
|
|
|
|
/// Read its documentation to learn more.
|
2024-03-15 03:21:55 +01:00
|
|
|
pub trait GenericArgsLowerer<'a, 'tcx> {
|
2023-02-01 14:23:51 +00:00
|
|
|
fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
|
2020-11-13 15:49:17 +01:00
|
|
|
|
|
|
|
fn provided_kind(
|
|
|
|
&mut self,
|
|
|
|
param: &ty::GenericParamDef,
|
2023-02-01 14:23:51 +00:00
|
|
|
arg: &GenericArg<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> ty::GenericArg<'tcx>;
|
2020-11-13 15:49:17 +01:00
|
|
|
|
|
|
|
fn inferred_kind(
|
|
|
|
&mut self,
|
2023-07-11 22:35:29 +01:00
|
|
|
args: Option<&[ty::GenericArg<'tcx>]>,
|
2020-11-13 15:49:17 +01:00
|
|
|
param: &ty::GenericParamDef,
|
|
|
|
infer_args: bool,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> ty::GenericArg<'tcx>;
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_lifetime(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2017-01-13 15:09:56 +02:00
|
|
|
lifetime: &hir::Lifetime,
|
2019-12-24 17:38:22 -05:00
|
|
|
def: Option<&ty::GenericParamDef>,
|
|
|
|
) -> ty::Region<'tcx> {
|
2017-01-04 23:23:11 +02:00
|
|
|
let tcx = self.tcx();
|
2023-11-24 19:28:19 +03:00
|
|
|
let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
|
2017-08-15 17:05:25 +02:00
|
|
|
|
2023-02-06 18:38:52 +00:00
|
|
|
match tcx.named_bound_var(lifetime.hir_id) {
|
|
|
|
Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
|
2013-10-28 17:37:10 -04:00
|
|
|
|
2023-02-06 18:38:52 +00:00
|
|
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
|
2020-10-26 14:18:31 -04:00
|
|
|
let name = lifetime_name(def_id.expect_local());
|
|
|
|
let br = ty::BoundRegion {
|
|
|
|
var: ty::BoundVar::from_u32(index),
|
|
|
|
kind: ty::BrNamed(def_id, name),
|
|
|
|
};
|
2023-11-13 14:00:05 +00:00
|
|
|
ty::Region::new_bound(tcx, debruijn, br)
|
2017-01-13 15:09:56 +02:00
|
|
|
}
|
|
|
|
|
2023-02-06 18:38:52 +00:00
|
|
|
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
2022-05-24 08:31:11 +02:00
|
|
|
let name = tcx.hir().ty_param_name(def_id.expect_local());
|
|
|
|
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
|
|
|
|
let generics = tcx.generics_of(item_def_id);
|
|
|
|
let index = generics.param_def_id_to_index[&def_id];
|
2024-05-24 01:57:06 +01:00
|
|
|
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
|
2017-01-04 23:23:11 +02:00
|
|
|
}
|
2016-08-05 06:30:41 +02:00
|
|
|
|
2023-02-06 18:38:52 +00:00
|
|
|
Some(rbv::ResolvedArg::Free(scope, id)) => {
|
2020-04-12 13:45:41 +01:00
|
|
|
let name = lifetime_name(id.expect_local());
|
2023-11-14 13:13:27 +00:00
|
|
|
ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name))
|
2017-01-04 23:23:11 +02:00
|
|
|
|
2018-09-26 17:32:23 +02:00
|
|
|
// (*) -- not late-bound, won't change
|
2017-01-04 14:32:44 +02:00
|
|
|
}
|
2017-01-04 23:23:11 +02:00
|
|
|
|
2023-09-02 21:29:27 +00:00
|
|
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar),
|
2023-02-18 03:28:43 +00:00
|
|
|
|
2017-01-25 17:32:44 +02:00
|
|
|
None => {
|
2022-11-05 22:41:07 +00:00
|
|
|
self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?lifetime, "unelided lifetime in signature");
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
// This indicates an illegal lifetime
|
|
|
|
// elision. `resolve_lifetime` should have
|
|
|
|
// reported an error in this case -- but if
|
|
|
|
// not, let's error out.
|
2023-05-29 17:54:53 +00:00
|
|
|
ty::Region::new_error_with_message(
|
|
|
|
tcx,
|
2023-02-13 13:03:45 +11:00
|
|
|
lifetime.ident.span,
|
|
|
|
"unelided lifetime in signature",
|
|
|
|
)
|
2019-12-24 17:38:22 -05:00
|
|
|
})
|
2017-01-25 17:32:44 +02:00
|
|
|
}
|
2022-06-28 15:18:07 +00:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-02-12 05:05:09 -05:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_generic_args_of_path_segment(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2016-05-11 08:48:12 +03:00
|
|
|
span: Span,
|
2016-08-08 23:39:49 +03:00
|
|
|
def_id: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
item_segment: &hir::PathSegment<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> GenericArgsRef<'tcx> {
|
2024-03-15 03:21:55 +01:00
|
|
|
let (args, _) = self.lower_generic_args_of_path(
|
2019-06-12 11:42:58 +03:00
|
|
|
span,
|
|
|
|
def_id,
|
2019-12-08 17:04:17 +00:00
|
|
|
&[],
|
2021-01-02 19:45:11 +01:00
|
|
|
item_segment,
|
2019-06-12 11:42:58 +03:00
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2019-06-12 11:42:58 +03:00
|
|
|
);
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(c) = item_segment.args().constraints.first() {
|
|
|
|
prohibit_assoc_item_constraint(self.tcx(), c, Some((def_id, item_segment, span)));
|
2020-04-24 13:58:41 -07:00
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
args
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower the generic arguments provided to some path.
|
2023-12-28 16:38:24 +01:00
|
|
|
///
|
2024-02-11 09:22:52 +01:00
|
|
|
/// If this is a trait reference, you also need to pass the self type `self_ty`.
|
|
|
|
/// The lowering process may involve applying defaulted type parameters.
|
2016-08-17 04:05:00 +03:00
|
|
|
///
|
2024-05-27 23:53:46 +02:00
|
|
|
/// Associated item constraints are not handled here! They are either lowered via
|
|
|
|
/// `lower_assoc_item_constraint` or rejected via `prohibit_assoc_item_constraint`.
|
2024-02-11 09:22:52 +01:00
|
|
|
///
|
|
|
|
/// ### Example
|
2019-06-05 21:08:36 +01:00
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (illustrative)
|
|
|
|
/// T: std::ops::Index<usize, Output = u32>
|
|
|
|
/// // ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4
|
2019-06-05 21:08:36 +01:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// 1. The `self_ty` here would refer to the type `T`.
|
|
|
|
/// 2. The path in question is the path to the trait `std::ops::Index`,
|
|
|
|
/// which will have been resolved to a `def_id`
|
|
|
|
/// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
|
2023-12-28 16:38:24 +01:00
|
|
|
/// parameters are returned in the `GenericArgsRef`
|
2024-05-27 23:53:46 +02:00
|
|
|
/// 4. Associated item constraints like `Output = u32` are contained in `generic_args.constraints`.
|
2019-06-05 21:08:36 +01:00
|
|
|
///
|
2016-08-17 04:05:00 +03:00
|
|
|
/// Note that the type listing given here is *exactly* what the user provided.
|
2019-12-08 17:04:17 +00:00
|
|
|
///
|
|
|
|
/// For (generic) associated types
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (illustrative)
|
2019-12-08 17:04:17 +00:00
|
|
|
/// <Vec<u8> as Iterable<u8>>::Iter::<'a>
|
|
|
|
/// ```
|
|
|
|
///
|
2023-07-11 22:35:29 +01:00
|
|
|
/// We have the parent args are the args for the parent trait:
|
2019-12-08 17:04:17 +00:00
|
|
|
/// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
|
2023-07-11 22:35:29 +01:00
|
|
|
/// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two
|
2019-12-08 17:04:17 +00:00
|
|
|
/// lists: `[Vec<u8>, u8, 'a]`.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self, span), ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_generic_args_of_path(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2016-05-11 08:48:12 +03:00
|
|
|
span: Span,
|
2016-08-08 23:39:49 +03:00
|
|
|
def_id: DefId,
|
2023-07-11 22:35:29 +01:00
|
|
|
parent_args: &[ty::GenericArg<'tcx>],
|
2024-03-15 02:19:29 +01:00
|
|
|
segment: &hir::PathSegment<'tcx>,
|
2019-12-24 17:38:22 -05:00
|
|
|
self_ty: Option<Ty<'tcx>>,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness: ty::BoundConstness,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
|
2016-05-11 08:48:12 +03:00
|
|
|
// If the type is parameterized by this region, then replace this
|
|
|
|
// region with the current anon region binding (in other words,
|
|
|
|
// whatever & would get replaced with).
|
2018-05-11 16:12:56 +01:00
|
|
|
|
2018-08-07 18:53:43 +01:00
|
|
|
let tcx = self.tcx();
|
2021-01-02 19:45:11 +01:00
|
|
|
let generics = tcx.generics_of(def_id);
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?generics);
|
2017-01-04 23:23:11 +02:00
|
|
|
|
2021-01-02 19:45:11 +01:00
|
|
|
if generics.has_self {
|
|
|
|
if generics.parent.is_some() {
|
2024-02-12 15:39:32 +09:00
|
|
|
// The parent is a trait so it should have at least one
|
|
|
|
// generic parameter for the `Self` type.
|
2023-07-11 22:35:29 +01:00
|
|
|
assert!(!parent_args.is_empty())
|
2019-12-08 17:04:17 +00:00
|
|
|
} else {
|
|
|
|
// This item (presumably a trait) needs a self-type.
|
|
|
|
assert!(self_ty.is_some());
|
|
|
|
}
|
|
|
|
} else {
|
2022-12-03 19:08:00 +00:00
|
|
|
assert!(self_ty.is_none());
|
2019-12-08 17:04:17 +00:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
|
2023-12-19 04:28:43 +00:00
|
|
|
let mut arg_count = check_generic_arg_count(
|
2018-12-26 00:07:31 +00:00
|
|
|
tcx,
|
2021-01-02 19:45:11 +01:00
|
|
|
def_id,
|
2024-03-15 02:19:29 +01:00
|
|
|
segment,
|
2021-09-30 19:38:50 +02:00
|
|
|
generics,
|
2018-08-20 12:52:56 +01:00
|
|
|
GenericArgPosition::Type,
|
2019-12-08 17:04:17 +00:00
|
|
|
self_ty.is_some(),
|
2018-08-08 00:01:47 +01:00
|
|
|
);
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2024-06-03 12:56:47 +00:00
|
|
|
if let Err(err) = &arg_count.correct {
|
|
|
|
self.set_tainted_by_errors(err.reported);
|
2024-01-10 10:31:06 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 18:25:28 +02:00
|
|
|
// Skip processing if type has no generic parameters.
|
|
|
|
// Traits always have `Self` as a generic parameter, which means they will not return early
|
2024-05-27 23:53:46 +02:00
|
|
|
// here and so associated item constraints will be handled regardless of whether there are
|
|
|
|
// any non-`Self` generic parameters.
|
2024-05-11 11:46:25 +02:00
|
|
|
if generics.is_own_empty() {
|
2023-07-11 22:35:29 +01:00
|
|
|
return (tcx.mk_args(parent_args), arg_count);
|
2020-10-21 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
struct GenericArgsCtxt<'a, 'tcx> {
|
|
|
|
lowerer: &'a dyn HirTyLowerer<'tcx>,
|
2020-11-13 15:49:17 +01:00
|
|
|
def_id: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
generic_args: &'a GenericArgs<'tcx>,
|
2020-11-13 15:49:17 +01:00
|
|
|
span: Span,
|
|
|
|
inferred_params: Vec<Span>,
|
|
|
|
infer_args: bool,
|
2024-06-03 13:16:56 +00:00
|
|
|
incorrect_args: &'a Result<(), GenericArgCountMismatch>,
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
2016-08-17 04:05:00 +03:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> {
|
2023-02-01 14:23:51 +00:00
|
|
|
fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
|
2020-11-13 15:49:17 +01:00
|
|
|
if did == self.def_id {
|
|
|
|
(Some(self.generic_args), self.infer_args)
|
2020-01-21 20:46:21 +00:00
|
|
|
} else {
|
|
|
|
// The last component of this tuple is unimportant.
|
|
|
|
(None, false)
|
|
|
|
}
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn provided_kind(
|
|
|
|
&mut self,
|
|
|
|
param: &ty::GenericParamDef,
|
2023-02-01 14:23:51 +00:00
|
|
|
arg: &GenericArg<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> ty::GenericArg<'tcx> {
|
2024-03-15 03:21:55 +01:00
|
|
|
let tcx = self.lowerer.tcx();
|
2021-12-13 03:16:00 +00:00
|
|
|
|
2024-06-03 13:21:17 +00:00
|
|
|
if let Err(incorrect) = self.incorrect_args {
|
|
|
|
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
2024-06-03 13:28:49 +00:00
|
|
|
// FIXME: use `param.to_error` once `provided_kind` is supplied a list of
|
|
|
|
// all previous generic args.
|
2024-06-03 13:21:17 +00:00
|
|
|
return match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => {
|
|
|
|
ty::Region::new_error(tcx, incorrect.reported).into()
|
|
|
|
}
|
|
|
|
GenericParamDefKind::Type { .. } => {
|
|
|
|
Ty::new_error(tcx, incorrect.reported).into()
|
|
|
|
}
|
|
|
|
GenericParamDefKind::Const { .. } => ty::Const::new_error(
|
|
|
|
tcx,
|
|
|
|
incorrect.reported,
|
|
|
|
Ty::new_error(tcx, incorrect.reported),
|
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 14:23:51 +00:00
|
|
|
let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
|
2021-12-13 03:16:00 +00:00
|
|
|
if has_default {
|
|
|
|
tcx.check_optional_stability(
|
|
|
|
param.def_id,
|
2022-08-29 11:24:46 +10:00
|
|
|
Some(arg.hir_id()),
|
2021-12-13 03:16:00 +00:00
|
|
|
arg.span(),
|
|
|
|
None,
|
2022-06-04 17:05:33 -05:00
|
|
|
AllowUnstable::No,
|
2021-12-13 03:16:00 +00:00
|
|
|
|_, _| {
|
|
|
|
// Default generic parameters may not be marked
|
|
|
|
// with stability attributes, i.e. when the
|
|
|
|
// default parameter was defined at the same time
|
|
|
|
// as the rest of the type. As such, we ignore missing
|
|
|
|
// stability attributes.
|
|
|
|
},
|
2022-04-11 18:12:26 -07:00
|
|
|
);
|
2021-12-13 03:16:00 +00:00
|
|
|
}
|
2024-03-15 03:21:55 +01:00
|
|
|
if let (hir::TyKind::Infer, false) = (&ty.kind, self.lowerer.allow_infer()) {
|
2021-12-13 03:16:00 +00:00
|
|
|
self.inferred_params.push(ty.span);
|
2023-07-05 20:13:26 +01:00
|
|
|
Ty::new_misc_error(tcx).into()
|
2021-12-13 03:16:00 +00:00
|
|
|
} else {
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lowerer.lower_ty(ty).into()
|
2021-12-13 03:16:00 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-11-13 15:49:17 +01:00
|
|
|
match (¶m.kind, arg) {
|
|
|
|
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lowerer.lower_lifetime(lt, Some(param)).into()
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
|
2021-12-13 03:16:00 +00:00
|
|
|
handle_ty_args(has_default, ty)
|
|
|
|
}
|
|
|
|
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
|
|
|
|
handle_ty_args(has_default, &inf.to_ty())
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
2020-08-11 00:02:45 +00:00
|
|
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
2023-02-19 10:02:00 +00:00
|
|
|
let did = ct.value.def_id;
|
|
|
|
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
|
|
|
|
ty::Const::from_anon_const(tcx, did).into()
|
2020-05-17 23:00:19 -04:00
|
|
|
}
|
2021-12-13 03:16:00 +00:00
|
|
|
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
2023-02-14 14:17:38 -07:00
|
|
|
let ty = tcx
|
|
|
|
.at(self.span)
|
|
|
|
.type_of(param.def_id)
|
|
|
|
.no_bound_vars()
|
|
|
|
.expect("const parameter types cannot be generic");
|
2024-03-15 03:21:55 +01:00
|
|
|
if self.lowerer.allow_infer() {
|
|
|
|
self.lowerer.ct_infer(ty, Some(param), inf.span).into()
|
2021-04-24 21:41:57 +00:00
|
|
|
} else {
|
|
|
|
self.inferred_params.push(inf.span);
|
2023-07-04 14:46:32 +01:00
|
|
|
ty::Const::new_misc_error(tcx, ty).into()
|
2021-04-24 21:41:57 +00:00
|
|
|
}
|
|
|
|
}
|
2023-12-15 03:19:46 +00:00
|
|
|
(kind, arg) => span_bug!(
|
|
|
|
self.span,
|
|
|
|
"mismatched path argument for kind {kind:?}: found arg {arg:?}"
|
|
|
|
),
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn inferred_kind(
|
|
|
|
&mut self,
|
2023-07-11 22:35:29 +01:00
|
|
|
args: Option<&[ty::GenericArg<'tcx>]>,
|
2020-11-13 15:49:17 +01:00
|
|
|
param: &ty::GenericParamDef,
|
|
|
|
infer_args: bool,
|
2023-07-11 22:35:29 +01:00
|
|
|
) -> ty::GenericArg<'tcx> {
|
2024-03-15 03:21:55 +01:00
|
|
|
let tcx = self.lowerer.tcx();
|
2024-06-03 13:16:56 +00:00
|
|
|
|
|
|
|
if let Err(incorrect) = self.incorrect_args {
|
|
|
|
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
2024-06-03 13:28:49 +00:00
|
|
|
// FIXME: use `param.to_error` once `inferred_kind` is supplied a list of
|
|
|
|
// all previous generic args.
|
2024-06-03 13:16:56 +00:00
|
|
|
return match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => {
|
|
|
|
ty::Region::new_error(tcx, incorrect.reported).into()
|
|
|
|
}
|
|
|
|
GenericParamDefKind::Type { .. } => {
|
|
|
|
Ty::new_error(tcx, incorrect.reported).into()
|
|
|
|
}
|
|
|
|
GenericParamDefKind::Const { .. } => ty::Const::new_error(
|
|
|
|
tcx,
|
|
|
|
incorrect.reported,
|
|
|
|
Ty::new_error(tcx, incorrect.reported),
|
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2018-07-24 02:59:22 +01:00
|
|
|
match param.kind {
|
2022-01-14 18:43:55 -08:00
|
|
|
GenericParamDefKind::Lifetime => self
|
2024-03-15 03:21:55 +01:00
|
|
|
.lowerer
|
2022-01-14 18:43:55 -08:00
|
|
|
.re_infer(Some(param), self.span)
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
debug!(?param, "unelided lifetime in signature");
|
|
|
|
|
|
|
|
// This indicates an illegal lifetime in a non-assoc-trait position
|
2023-05-29 17:54:53 +00:00
|
|
|
ty::Region::new_error_with_message(
|
|
|
|
tcx,
|
2023-02-13 13:03:45 +11:00
|
|
|
self.span,
|
|
|
|
"unelided lifetime in signature",
|
|
|
|
)
|
2022-01-14 18:43:55 -08:00
|
|
|
})
|
|
|
|
.into(),
|
2018-07-24 02:59:22 +01:00
|
|
|
GenericParamDefKind::Type { has_default, .. } => {
|
2019-06-07 10:18:03 +01:00
|
|
|
if !infer_args && has_default {
|
2018-07-24 02:59:22 +01:00
|
|
|
// No type parameter provided, but a default exists.
|
2023-07-11 22:35:29 +01:00
|
|
|
let args = args.unwrap();
|
|
|
|
if args.iter().any(|arg| match arg.unpack() {
|
2022-08-07 21:03:28 +02:00
|
|
|
GenericArgKind::Type(ty) => ty.references_error(),
|
|
|
|
_ => false,
|
|
|
|
}) {
|
|
|
|
// Avoid ICE #86756 when type error recovery goes awry.
|
2023-07-05 20:13:26 +01:00
|
|
|
return Ty::new_misc_error(tcx).into();
|
2018-07-24 17:47:31 +01:00
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into()
|
2019-06-07 10:18:03 +01:00
|
|
|
} else if infer_args {
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lowerer.ty_infer(Some(param), self.span).into()
|
2018-05-14 18:27:13 +01:00
|
|
|
} else {
|
2018-07-24 02:59:22 +01:00
|
|
|
// We've already errored above about the mismatch.
|
2023-07-05 20:13:26 +01:00
|
|
|
Ty::new_misc_error(tcx).into()
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
2018-05-15 13:15:49 +01:00
|
|
|
}
|
2023-09-11 13:18:36 +00:00
|
|
|
GenericParamDefKind::Const { has_default, .. } => {
|
2023-02-14 14:17:38 -07:00
|
|
|
let ty = tcx
|
|
|
|
.at(self.span)
|
|
|
|
.type_of(param.def_id)
|
|
|
|
.no_bound_vars()
|
|
|
|
.expect("const parameter types cannot be generic");
|
2023-02-22 22:19:41 +00:00
|
|
|
if let Err(guar) = ty.error_reported() {
|
2023-07-04 14:46:32 +01:00
|
|
|
return ty::Const::new_error(tcx, guar, ty).into();
|
2022-11-02 14:47:48 +09:00
|
|
|
}
|
2023-07-25 05:58:53 +00:00
|
|
|
// FIXME(effects) see if we should special case effect params here
|
2020-08-11 00:02:45 +00:00
|
|
|
if !infer_args && has_default {
|
2023-07-11 22:35:29 +01:00
|
|
|
tcx.const_param_default(param.def_id)
|
|
|
|
.instantiate(tcx, args.unwrap())
|
|
|
|
.into()
|
2020-08-11 00:02:45 +00:00
|
|
|
} else {
|
2021-03-01 12:50:09 +01:00
|
|
|
if infer_args {
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lowerer.ct_infer(ty, Some(param), self.span).into()
|
2020-08-11 00:02:45 +00:00
|
|
|
} else {
|
2021-03-01 12:50:09 +01:00
|
|
|
// We've already errored above about the mismatch.
|
2023-07-04 14:46:32 +01:00
|
|
|
ty::Const::new_misc_error(tcx, ty).into()
|
2020-08-11 00:02:45 +00:00
|
|
|
}
|
2019-06-06 01:55:09 +01:00
|
|
|
}
|
2019-02-20 01:16:42 +00:00
|
|
|
}
|
2018-07-24 17:47:31 +01:00
|
|
|
}
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
}
|
2023-12-18 17:55:55 +01:00
|
|
|
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
2023-12-19 04:28:43 +00:00
|
|
|
&& generics.has_self
|
|
|
|
&& !tcx.has_attr(def_id, sym::const_trait)
|
|
|
|
{
|
2024-06-03 12:56:47 +00:00
|
|
|
let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
2023-12-18 17:55:55 +01:00
|
|
|
span,
|
|
|
|
modifier: constness.as_str(),
|
|
|
|
});
|
2024-06-03 12:56:47 +00:00
|
|
|
self.set_tainted_by_errors(reported);
|
|
|
|
arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] });
|
2023-12-19 04:28:43 +00:00
|
|
|
}
|
2024-06-03 13:16:56 +00:00
|
|
|
|
|
|
|
let mut args_ctx = GenericArgsCtxt {
|
|
|
|
lowerer: self,
|
|
|
|
def_id,
|
|
|
|
span,
|
|
|
|
generic_args: segment.args(),
|
|
|
|
inferred_params: vec![],
|
|
|
|
infer_args: segment.infer_args,
|
|
|
|
incorrect_args: &arg_count.correct,
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
let args = lower_generic_args(
|
2020-11-13 15:49:17 +01:00
|
|
|
tcx,
|
|
|
|
def_id,
|
2023-07-11 22:35:29 +01:00
|
|
|
parent_args,
|
2020-11-13 15:49:17 +01:00
|
|
|
self_ty.is_some(),
|
|
|
|
self_ty,
|
2020-10-26 14:18:31 -04:00
|
|
|
&arg_count,
|
2023-07-11 22:35:29 +01:00
|
|
|
&mut args_ctx,
|
2018-07-24 17:47:31 +01:00
|
|
|
);
|
2019-12-12 17:26:19 -08:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
(args, arg_count)
|
2020-10-26 14:18:31 -04:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_generic_args_of_assoc_item(
|
2019-12-08 17:04:17 +00:00
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
item_def_id: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
item_segment: &hir::PathSegment<'tcx>,
|
2023-07-11 22:35:29 +01:00
|
|
|
parent_args: GenericArgsRef<'tcx>,
|
|
|
|
) -> GenericArgsRef<'tcx> {
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?span, ?item_def_id, ?item_segment);
|
2024-03-15 03:21:55 +01:00
|
|
|
let (args, _) = self.lower_generic_args_of_path(
|
2022-08-22 04:28:40 +00:00
|
|
|
span,
|
|
|
|
item_def_id,
|
2023-07-11 22:35:29 +01:00
|
|
|
parent_args,
|
2022-08-22 04:28:40 +00:00
|
|
|
item_segment,
|
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2022-09-27 00:45:50 +00:00
|
|
|
);
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(c) = item_segment.args().constraints.first() {
|
|
|
|
prohibit_assoc_item_constraint(self.tcx(), c, Some((item_def_id, item_segment, span)));
|
2022-09-27 00:45:50 +00:00
|
|
|
}
|
|
|
|
args
|
2019-12-08 17:04:17 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a trait reference as found in an impl header as the implementee.
|
2016-05-11 08:48:12 +03:00
|
|
|
///
|
2024-02-11 09:22:52 +01:00
|
|
|
/// The self type `self_ty` is the implementer of the trait.
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_impl_trait_ref(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2023-02-01 14:23:51 +00:00
|
|
|
trait_ref: &hir::TraitRef<'tcx>,
|
2019-12-24 17:38:22 -05:00
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
) -> ty::TraitRef<'tcx> {
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
|
|
|
GenericsArgsErrExtend::None,
|
|
|
|
);
|
2017-05-15 15:21:01 +09:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_mono_trait_ref(
|
2019-12-24 17:38:22 -05:00
|
|
|
trait_ref.path.span,
|
2020-03-23 20:27:59 +01:00
|
|
|
trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
|
2019-12-24 17:38:22 -05:00
|
|
|
self_ty,
|
|
|
|
trait_ref.path.segments.last().unwrap(),
|
2022-01-12 23:13:52 +01:00
|
|
|
true,
|
2023-07-25 05:58:53 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-02-15 15:09:26 -05:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a polymorphic trait reference given a self type into `bounds`.
|
2023-11-23 05:34:29 +00:00
|
|
|
///
|
2024-02-11 09:22:52 +01:00
|
|
|
/// *Polymorphic* in the sense that it may bind late-bound vars.
|
2023-11-23 05:34:29 +00:00
|
|
|
///
|
2024-05-27 23:53:46 +02:00
|
|
|
/// This may generate auxiliary bounds iff the trait reference contains associated item constraints.
|
2024-02-11 09:22:52 +01:00
|
|
|
///
|
|
|
|
/// ### Example
|
2023-11-23 05:34:29 +00:00
|
|
|
///
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the
|
|
|
|
///
|
2024-05-27 23:53:46 +02:00
|
|
|
/// 1. *trait predicate* `<Ty as Iterator>` (known as `Ty: Iterator` in the surface syntax) and the
|
2024-02-11 09:22:52 +01:00
|
|
|
/// 2. *projection predicate* `<Ty as Iterator>::Item = u32`
|
|
|
|
///
|
|
|
|
/// to `bounds`.
|
|
|
|
///
|
|
|
|
/// ### A Note on Binders
|
|
|
|
///
|
|
|
|
/// Against our usual convention, there is an implied binder around the `self_ty` and the
|
|
|
|
/// `trait_ref` here. So they may reference late-bound vars.
|
2023-11-23 05:34:29 +00:00
|
|
|
///
|
|
|
|
/// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
|
2024-02-11 09:22:52 +01:00
|
|
|
/// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`.
|
|
|
|
/// The lowered poly-trait-ref will track this binder explicitly, however.
|
2024-03-16 02:33:21 +01:00
|
|
|
#[instrument(level = "debug", skip(self, span, constness, bounds))]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub(crate) fn lower_poly_trait_ref(
|
2021-08-15 04:17:36 -04:00
|
|
|
&self,
|
2023-02-01 14:23:51 +00:00
|
|
|
trait_ref: &hir::TraitRef<'tcx>,
|
2021-08-15 04:17:36 -04:00
|
|
|
span: Span,
|
|
|
|
constness: ty::BoundConstness,
|
2024-03-21 15:45:28 -04:00
|
|
|
polarity: ty::PredicatePolarity,
|
2023-11-23 05:34:29 +00:00
|
|
|
self_ty: Ty<'tcx>,
|
2021-08-15 04:17:36 -04:00
|
|
|
bounds: &mut Bounds<'tcx>,
|
2023-04-18 23:55:05 +00:00
|
|
|
only_self_bounds: OnlySelfBounds,
|
2021-08-15 04:17:36 -04:00
|
|
|
) -> GenericArgCountResult {
|
2023-11-23 05:34:29 +00:00
|
|
|
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
|
|
|
let trait_segment = trait_ref.path.segments.last().unwrap();
|
|
|
|
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
|
|
|
GenericsArgsErrExtend::None,
|
|
|
|
);
|
2023-11-23 05:34:29 +00:00
|
|
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let (generic_args, arg_count) = self.lower_generic_args_of_path(
|
2023-11-23 05:34:29 +00:00
|
|
|
trait_ref.path.span,
|
2021-08-15 04:17:36 -04:00
|
|
|
trait_def_id,
|
|
|
|
&[],
|
|
|
|
trait_segment,
|
|
|
|
Some(self_ty),
|
2022-11-04 16:28:01 +00:00
|
|
|
constness,
|
2021-08-15 04:17:36 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
let tcx = self.tcx();
|
2023-11-23 05:34:29 +00:00
|
|
|
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
|
2021-08-15 04:17:36 -04:00
|
|
|
debug!(?bound_vars);
|
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let poly_trait_ref = ty::Binder::bind_with_vars(
|
|
|
|
ty::TraitRef::new(tcx, trait_def_id, generic_args),
|
|
|
|
bound_vars,
|
|
|
|
);
|
2021-08-15 04:17:36 -04:00
|
|
|
|
2023-12-28 16:38:24 +01:00
|
|
|
debug!(?poly_trait_ref);
|
2023-07-29 08:20:25 +00:00
|
|
|
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
2021-08-15 04:17:36 -04:00
|
|
|
|
2024-05-27 23:53:46 +02:00
|
|
|
let mut dup_constraints = FxIndexMap::default();
|
|
|
|
for constraint in trait_segment.args().constraints {
|
|
|
|
// Don't register any associated item constraints for negative bounds,
|
|
|
|
// since we should have emitted an error for them earlier, and they
|
|
|
|
// would not be well-formed!
|
2024-03-21 15:46:40 -04:00
|
|
|
if polarity != ty::PredicatePolarity::Positive {
|
2024-02-14 15:17:15 +11:00
|
|
|
assert!(
|
|
|
|
self.tcx().dcx().has_errors().is_some(),
|
2024-05-27 23:53:46 +02:00
|
|
|
"negative trait bounds should not have assoc item constraints",
|
2023-11-30 15:01:11 +11:00
|
|
|
);
|
2023-04-25 06:37:24 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
// Specify type to assert that error was already reported in `Err` case.
|
2024-05-27 23:53:46 +02:00
|
|
|
let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint(
|
2023-11-23 05:34:29 +00:00
|
|
|
trait_ref.hir_ref_id,
|
2021-08-15 04:17:36 -04:00
|
|
|
poly_trait_ref,
|
2024-05-27 23:53:46 +02:00
|
|
|
constraint,
|
2021-08-15 04:17:36 -04:00
|
|
|
bounds,
|
2024-05-27 23:53:46 +02:00
|
|
|
&mut dup_constraints,
|
|
|
|
constraint.span,
|
2023-04-18 23:55:05 +00:00
|
|
|
only_self_bounds,
|
2021-08-15 04:17:36 -04:00
|
|
|
);
|
2022-01-23 12:34:26 -06:00
|
|
|
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
|
2021-08-15 04:17:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
arg_count
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a monomorphic trait reference given a self type while prohibiting associated item bindings.
|
|
|
|
///
|
|
|
|
/// *Monomorphic* in the sense that it doesn't bind any late-bound vars.
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_mono_trait_ref(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2019-03-16 00:04:02 +00:00
|
|
|
span: Span,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
self_ty: Ty<'tcx>,
|
2023-02-01 14:23:51 +00:00
|
|
|
trait_segment: &hir::PathSegment<'tcx>,
|
2022-01-12 23:13:52 +01:00
|
|
|
is_impl: bool,
|
2024-02-11 09:22:52 +01:00
|
|
|
// FIXME(effects): Move all host param things in HIR ty lowering to AST lowering.
|
2022-11-04 16:28:01 +00:00
|
|
|
constness: ty::BoundConstness,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> ty::TraitRef<'tcx> {
|
2024-03-15 02:19:29 +01:00
|
|
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let (generic_args, _) = self.lower_generic_args_of_path(
|
2022-01-12 23:13:52 +01:00
|
|
|
span,
|
|
|
|
trait_def_id,
|
2024-03-15 02:19:29 +01:00
|
|
|
&[],
|
2022-01-12 23:13:52 +01:00
|
|
|
trait_segment,
|
2024-03-15 02:19:29 +01:00
|
|
|
Some(self_ty),
|
2022-10-20 09:39:09 +00:00
|
|
|
constness,
|
2022-01-12 23:13:52 +01:00
|
|
|
);
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(c) = trait_segment.args().constraints.first() {
|
|
|
|
prohibit_assoc_item_constraint(
|
|
|
|
self.tcx(),
|
|
|
|
c,
|
|
|
|
Some((trait_def_id, trait_segment, span)),
|
|
|
|
);
|
2020-04-24 13:58:41 -07:00
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-02-15 15:09:26 -05:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_trait_that_defines_assoc_item(
|
2023-03-05 01:08:17 +00:00
|
|
|
&self,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
assoc_kind: ty::AssocKind,
|
|
|
|
assoc_name: Ident,
|
|
|
|
) -> bool {
|
2022-01-10 23:39:21 +00:00
|
|
|
self.tcx()
|
|
|
|
.associated_items(trait_def_id)
|
2023-03-05 01:08:17 +00:00
|
|
|
.find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
|
2022-01-10 23:39:21 +00:00
|
|
|
.is_some()
|
|
|
|
}
|
2016-11-10 02:06:34 +02:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_path_segment(
|
2019-12-01 16:08:58 +01:00
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
did: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
item_segment: &hir::PathSegment<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
) -> Ty<'tcx> {
|
2023-08-06 23:02:27 +02:00
|
|
|
let tcx = self.tcx();
|
2024-03-15 03:21:55 +01:00
|
|
|
let args = self.lower_generic_args_of_path_segment(span, did, item_segment);
|
2023-03-07 12:03:11 +00:00
|
|
|
|
2023-09-26 02:15:32 +00:00
|
|
|
if let DefKind::TyAlias = tcx.def_kind(did)
|
|
|
|
&& tcx.type_alias_is_lazy(did)
|
|
|
|
{
|
2023-06-30 13:54:15 +00:00
|
|
|
// Type aliases defined in crates that have the
|
2023-08-06 23:02:27 +02:00
|
|
|
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
|
2023-03-07 12:03:11 +00:00
|
|
|
// then actually instantiate the where bounds of.
|
2023-10-18 13:57:19 +02:00
|
|
|
let alias_ty = ty::AliasTy::new(tcx, did, args);
|
2023-08-06 23:02:27 +02:00
|
|
|
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
2023-03-07 12:03:11 +00:00
|
|
|
} else {
|
2023-09-26 02:15:32 +00:00
|
|
|
tcx.at(span).type_of(did).instantiate(tcx, args)
|
2023-03-07 12:03:11 +00:00
|
|
|
}
|
2014-02-02 00:09:11 +11:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`.
|
|
|
|
///
|
|
|
|
/// This fails if there is no such bound in the list of candidates or if there are multiple
|
|
|
|
/// candidates in which case it reports ambiguity.
|
|
|
|
///
|
|
|
|
/// `ty_param_def_id` is the `LocalDefId` of the type parameter.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all, ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_single_ty_param_bound_for_assoc_ty(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2020-04-12 13:45:41 +01:00
|
|
|
ty_param_def_id: LocalDefId,
|
2020-04-19 13:00:18 +02:00
|
|
|
assoc_name: Ident,
|
2019-12-24 17:38:22 -05:00
|
|
|
span: Span,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?ty_param_def_id, ?assoc_name, ?span);
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
2015-02-26 19:15:57 +01:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name).predicates;
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!("predicates={:#?}", predicates);
|
2019-07-12 06:31:42 -04:00
|
|
|
|
2022-04-08 23:06:20 +02:00
|
|
|
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
|
2024-03-15 03:21:55 +01:00
|
|
|
self.probe_single_bound_for_assoc_item(
|
2019-12-24 17:38:22 -05:00
|
|
|
|| {
|
2023-05-03 20:13:32 +00:00
|
|
|
traits::transitive_bounds_that_define_assoc_item(
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx,
|
2023-06-22 18:17:13 +00:00
|
|
|
predicates
|
|
|
|
.iter()
|
|
|
|
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))),
|
2020-12-03 20:10:55 -03:00
|
|
|
assoc_name,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
|
|
|
},
|
2023-02-26 23:51:49 +00:00
|
|
|
param_name,
|
2023-09-29 03:16:11 +00:00
|
|
|
Some(ty_param_def_id),
|
2023-11-24 09:53:10 +01:00
|
|
|
ty::AssocKind::Type,
|
2019-12-18 20:35:18 +01:00
|
|
|
assoc_name,
|
|
|
|
span,
|
2023-02-26 23:51:49 +00:00
|
|
|
None,
|
2019-12-18 20:35:18 +01:00
|
|
|
)
|
2015-02-24 09:24:42 -05:00
|
|
|
}
|
2015-02-17 17:11:01 -05:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Search for a single trait bound whose trait defines the associated item given by `assoc_name`.
|
|
|
|
///
|
|
|
|
/// This fails if there is no such bound in the list of candidates or if there are multiple
|
|
|
|
/// candidates in which case it reports ambiguity.
|
2024-05-27 23:53:46 +02:00
|
|
|
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_single_bound_for_assoc_item<I>(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
|
|
|
all_candidates: impl Fn() -> I,
|
2023-02-26 23:51:49 +00:00
|
|
|
ty_param_name: impl Display,
|
2023-09-29 03:16:11 +00:00
|
|
|
ty_param_def_id: Option<LocalDefId>,
|
2023-11-24 09:53:10 +01:00
|
|
|
assoc_kind: ty::AssocKind,
|
2020-04-19 13:00:18 +02:00
|
|
|
assoc_name: Ident,
|
2019-12-24 17:38:22 -05:00
|
|
|
span: Span,
|
2024-05-27 23:53:46 +02:00
|
|
|
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
|
2019-12-24 17:38:22 -05:00
|
|
|
where
|
|
|
|
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
2016-05-11 08:48:12 +03:00
|
|
|
{
|
2023-11-24 09:53:10 +01:00
|
|
|
let tcx = self.tcx();
|
|
|
|
|
2023-03-05 01:08:17 +00:00
|
|
|
let mut matching_candidates = all_candidates().filter(|r| {
|
2024-03-15 03:21:55 +01:00
|
|
|
self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_name)
|
2023-03-05 01:08:17 +00:00
|
|
|
});
|
2022-02-02 16:42:37 +00:00
|
|
|
|
2024-01-08 01:07:14 +00:00
|
|
|
let Some(bound) = matching_candidates.next() else {
|
2023-11-24 09:53:10 +01:00
|
|
|
let reported = self.complain_about_assoc_item_not_found(
|
|
|
|
all_candidates,
|
|
|
|
&ty_param_name.to_string(),
|
|
|
|
ty_param_def_id,
|
|
|
|
assoc_kind,
|
|
|
|
assoc_name,
|
|
|
|
span,
|
2024-05-27 23:53:46 +02:00
|
|
|
constraint,
|
2023-11-24 09:53:10 +01:00
|
|
|
);
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(reported);
|
2023-11-24 09:53:10 +01:00
|
|
|
return Err(reported);
|
2016-11-27 06:54:50 -07:00
|
|
|
};
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?bound);
|
2019-07-12 06:31:42 -04:00
|
|
|
|
2024-01-08 01:07:14 +00:00
|
|
|
if let Some(bound2) = matching_candidates.next() {
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?bound2);
|
2019-07-12 06:31:42 -04:00
|
|
|
|
2023-11-24 09:53:10 +01:00
|
|
|
let assoc_kind_str = assoc_kind_str(assoc_kind);
|
|
|
|
let ty_param_name = &ty_param_name.to_string();
|
2023-12-18 22:21:37 +11:00
|
|
|
let mut err = tcx.dcx().create_err(crate::errors::AmbiguousAssocItem {
|
2023-11-24 09:53:10 +01:00
|
|
|
span,
|
|
|
|
assoc_kind: assoc_kind_str,
|
|
|
|
assoc_name,
|
|
|
|
ty_param_name,
|
|
|
|
});
|
|
|
|
// Provide a more specific error code index entry for equality bindings.
|
|
|
|
err.code(
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(constraint) = constraint
|
|
|
|
&& let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
|
2023-11-24 09:53:10 +01:00
|
|
|
{
|
Stop using `String` for error codes.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
2024-01-14 10:57:07 +11:00
|
|
|
E0222
|
2023-11-24 09:53:10 +01:00
|
|
|
} else {
|
Stop using `String` for error codes.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
2024-01-14 10:57:07 +11:00
|
|
|
E0221
|
2023-11-24 09:53:10 +01:00
|
|
|
},
|
|
|
|
);
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2024-05-27 23:53:46 +02:00
|
|
|
// FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
|
2023-11-24 09:53:10 +01:00
|
|
|
// FIXME: Turn this into a structured, translateable & more actionable suggestion.
|
2019-12-12 21:15:19 -08:00
|
|
|
let mut where_bounds = vec![];
|
2023-11-24 09:53:10 +01:00
|
|
|
for bound in [bound, bound2].into_iter().chain(matching_candidates) {
|
2020-02-17 13:09:01 -08:00
|
|
|
let bound_id = bound.def_id();
|
2023-11-24 09:53:10 +01:00
|
|
|
let bound_span = tcx
|
2020-02-17 13:09:01 -08:00
|
|
|
.associated_items(bound_id)
|
2023-11-24 09:53:10 +01:00
|
|
|
.find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id)
|
|
|
|
.and_then(|item| tcx.hir().span_if_local(item.def_id));
|
2016-11-27 06:54:50 -07:00
|
|
|
|
2019-12-12 14:48:46 -08:00
|
|
|
if let Some(bound_span) = bound_span {
|
2019-12-24 17:38:22 -05:00
|
|
|
err.span_label(
|
2019-12-12 14:48:46 -08:00
|
|
|
bound_span,
|
2023-11-24 22:09:59 +00:00
|
|
|
format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),),
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(constraint) = constraint {
|
|
|
|
match constraint.kind {
|
|
|
|
hir::AssocItemConstraintKind::Equality { term } => {
|
2023-12-28 16:38:24 +01:00
|
|
|
let term: ty::Term<'_> = match term {
|
2024-03-15 03:21:55 +01:00
|
|
|
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
2023-12-28 16:38:24 +01:00
|
|
|
hir::Term::Const(ct) => {
|
|
|
|
ty::Const::from_anon_const(tcx, ct.def_id).into()
|
|
|
|
}
|
|
|
|
};
|
2023-11-24 09:53:10 +01:00
|
|
|
// FIXME(#97583): This isn't syntactically well-formed!
|
|
|
|
where_bounds.push(format!(
|
|
|
|
" T: {trait}::{assoc_name} = {term}",
|
|
|
|
trait = bound.print_only_trait_path(),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// FIXME: Provide a suggestion.
|
2024-05-27 23:53:46 +02:00
|
|
|
hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
|
2023-11-24 09:53:10 +01:00
|
|
|
}
|
2019-12-12 21:15:19 -08:00
|
|
|
} else {
|
2021-08-10 10:53:43 +00:00
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span.with_hi(assoc_name.span.lo()),
|
2023-10-16 18:25:11 +00:00
|
|
|
"use fully-qualified syntax to disambiguate",
|
2023-09-29 03:16:11 +00:00
|
|
|
format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()),
|
2019-12-12 21:15:19 -08:00
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
2019-12-12 14:48:46 -08:00
|
|
|
} else {
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
err.note(format!(
|
2023-11-24 09:53:10 +01:00
|
|
|
"associated {assoc_kind_str} `{assoc_name}` could derive from `{}`",
|
2019-12-12 14:48:46 -08:00
|
|
|
bound.print_only_trait_path(),
|
|
|
|
));
|
2016-10-23 21:53:31 +03:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-12-12 21:15:19 -08:00
|
|
|
if !where_bounds.is_empty() {
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
err.help(format!(
|
2019-12-12 21:15:19 -08:00
|
|
|
"consider introducing a new type parameter `T` and adding `where` constraints:\
|
2023-09-29 03:16:11 +00:00
|
|
|
\n where\n T: {ty_param_name},\n{}",
|
2019-12-12 21:15:19 -08:00
|
|
|
where_bounds.join(",\n"),
|
|
|
|
));
|
|
|
|
}
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = err.emit();
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(reported);
|
2019-12-12 21:15:19 -08:00
|
|
|
if !where_bounds.is_empty() {
|
2022-01-22 18:49:12 -06:00
|
|
|
return Err(reported);
|
2019-12-12 21:15:19 -08:00
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
2022-02-02 16:42:37 +00:00
|
|
|
|
2020-03-20 15:03:11 +01:00
|
|
|
Ok(bound)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-04-03 17:13:52 +13:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a [type-relative] path referring to an associated type or to an enum variant.
|
|
|
|
///
|
|
|
|
/// If the path refers to an enum variant and `permit_variants` holds,
|
|
|
|
/// the returned type is simply the provided self type `qself_ty`.
|
|
|
|
///
|
|
|
|
/// A path like `A::B::C::D` is understood as `<A::B::C>::D`. I.e.,
|
|
|
|
/// `qself_ty` / `qself` is `A::B::C` and `assoc_segment` is `D`.
|
|
|
|
/// We return the lowered type and the `DefId` for the whole path.
|
|
|
|
///
|
|
|
|
/// We only support associated type paths whose self type is a type parameter or a `Self`
|
|
|
|
/// type alias (in a trait impl) like `T::Ty` (where `T` is a ty param) or `Self::Ty`.
|
|
|
|
/// We **don't** support paths whose self type is an arbitrary type like `Struct::Ty` where
|
|
|
|
/// struct `Struct` impls an in-scope trait that defines an associated type called `Ty`.
|
|
|
|
/// For the latter case, we report ambiguity.
|
|
|
|
/// While desirable to support, the implemention would be non-trivial. Tracked in [#22519].
|
|
|
|
///
|
|
|
|
/// At the time of writing, *inherent associated types* are also resolved here. This however
|
|
|
|
/// is [problematic][iat]. A proper implementation would be as non-trivial as the one
|
|
|
|
/// described in the previous paragraph and their modeling of projections would likely be
|
|
|
|
/// very similar in nature.
|
|
|
|
///
|
|
|
|
/// [type-relative]: hir::QPath::TypeRelative
|
|
|
|
/// [#22519]: https://github.com/rust-lang/rust/issues/22519
|
|
|
|
/// [iat]: https://github.com/rust-lang/rust/issues/8995#issuecomment-1569208403
|
|
|
|
//
|
2021-03-18 03:02:44 +03:00
|
|
|
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
|
2022-03-30 15:14:15 -04:00
|
|
|
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all, ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_assoc_path(
|
2019-01-10 23:23:30 +03:00
|
|
|
&self,
|
2024-03-06 17:24:13 +11:00
|
|
|
hir_ref_id: HirId,
|
2019-01-10 23:23:30 +03:00
|
|
|
span: Span,
|
|
|
|
qself_ty: Ty<'tcx>,
|
2024-03-22 14:20:31 +08:00
|
|
|
qself: &'tcx hir::Ty<'tcx>,
|
|
|
|
assoc_segment: &'tcx hir::PathSegment<'tcx>,
|
2019-01-10 23:23:30 +03:00
|
|
|
permit_variants: bool,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorGuaranteed> {
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(%qself_ty, ?assoc_segment.ident);
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
2024-02-11 09:24:35 +01:00
|
|
|
|
2019-01-10 23:23:30 +03:00
|
|
|
let assoc_ident = assoc_segment.ident;
|
2023-01-09 16:30:40 +00:00
|
|
|
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
|
2022-05-27 19:53:31 -07:00
|
|
|
path.res
|
|
|
|
} else {
|
|
|
|
Res::Err
|
|
|
|
};
|
2016-05-11 08:48:12 +03:00
|
|
|
|
2023-02-17 18:42:08 +01:00
|
|
|
// Check if we have an enum variant or an inherent associated type.
|
2019-01-10 23:23:30 +03:00
|
|
|
let mut variant_resolution = None;
|
2022-10-29 16:19:57 +03:00
|
|
|
if let Some(adt_def) = self.probe_adt(span, qself_ty) {
|
2019-01-10 23:23:30 +03:00
|
|
|
if adt_def.is_enum() {
|
2019-12-24 17:38:22 -05:00
|
|
|
let variant_def = adt_def
|
2022-03-05 07:28:41 +11:00
|
|
|
.variants()
|
2019-12-24 17:38:22 -05:00
|
|
|
.iter()
|
2022-03-05 07:28:41 +11:00
|
|
|
.find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident(tcx), adt_def.did()));
|
2019-01-10 23:23:30 +03:00
|
|
|
if let Some(variant_def) = variant_def {
|
|
|
|
if permit_variants {
|
2021-05-07 10:41:04 +08:00
|
|
|
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
slice::from_ref(assoc_segment).iter(),
|
|
|
|
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
|
|
|
|
);
|
2019-04-20 19:46:19 +03:00
|
|
|
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
|
2019-01-10 23:23:30 +03:00
|
|
|
} else {
|
2019-04-20 19:46:19 +03:00
|
|
|
variant_resolution = Some(variant_def.def_id);
|
2019-01-10 23:23:30 +03:00
|
|
|
}
|
|
|
|
}
|
2022-10-27 07:11:15 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
|
2024-03-15 03:21:55 +01:00
|
|
|
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
|
2022-12-08 13:31:21 +01:00
|
|
|
assoc_ident,
|
|
|
|
assoc_segment,
|
|
|
|
adt_def.did(),
|
|
|
|
qself_ty,
|
|
|
|
hir_ref_id,
|
|
|
|
span,
|
|
|
|
)? {
|
|
|
|
return Ok((ty, DefKind::AssocTy, did));
|
2019-01-10 23:23:30 +03:00
|
|
|
}
|
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
|
|
|
|
// Find the type of the associated item, and the trait where the associated
|
|
|
|
// item is declared.
|
2020-08-03 00:49:11 +02:00
|
|
|
let bound = match (&qself_ty.kind(), qself_res) {
|
2022-09-16 11:45:33 +10:00
|
|
|
(_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
|
2018-12-26 16:38:35 +00:00
|
|
|
// `Self` in an impl of a trait -- we have a concrete self type and a
|
2016-05-11 08:48:12 +03:00
|
|
|
// trait reference.
|
2023-01-10 14:57:22 -07:00
|
|
|
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
|
2022-02-19 00:44:45 +01:00
|
|
|
// A cycle error occurred, most likely.
|
2024-02-17 01:23:40 +11:00
|
|
|
tcx.dcx().span_bug(span, "expected cycle error");
|
2017-02-19 00:15:30 +03:00
|
|
|
};
|
2017-02-14 11:32:00 +02:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
self.probe_single_bound_for_assoc_item(
|
2023-07-11 22:35:29 +01:00
|
|
|
|| {
|
|
|
|
traits::supertraits(
|
|
|
|
tcx,
|
|
|
|
ty::Binder::dummy(trait_ref.instantiate_identity()),
|
|
|
|
)
|
|
|
|
},
|
2023-02-26 23:51:49 +00:00
|
|
|
kw::SelfUpper,
|
2023-09-29 03:16:11 +00:00
|
|
|
None,
|
2023-11-24 09:53:10 +01:00
|
|
|
ty::AssocKind::Type,
|
2019-12-18 20:35:18 +01:00
|
|
|
assoc_ident,
|
2019-12-24 17:38:22 -05:00
|
|
|
span,
|
2023-02-26 23:51:49 +00:00
|
|
|
None,
|
2019-12-18 20:35:18 +01:00
|
|
|
)?
|
2015-07-25 21:25:51 +03:00
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
(
|
|
|
|
&ty::Param(_),
|
2022-09-16 11:45:33 +10:00
|
|
|
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
|
2024-03-15 03:21:55 +01:00
|
|
|
) => self.probe_single_ty_param_bound_for_assoc_ty(
|
|
|
|
param_did.expect_local(),
|
|
|
|
assoc_ident,
|
|
|
|
span,
|
|
|
|
)?,
|
2019-01-10 23:23:30 +03:00
|
|
|
_ => {
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = if variant_resolution.is_some() {
|
2019-01-10 23:23:30 +03:00
|
|
|
// Variant in type position
|
2023-07-25 23:17:39 +02:00
|
|
|
let msg = format!("expected type, found variant `{assoc_ident}`");
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().span_err(span, msg)
|
2019-01-10 23:23:30 +03:00
|
|
|
} else if qself_ty.is_enum() {
|
2024-01-04 09:08:36 +11:00
|
|
|
let mut err = struct_span_code_err!(
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx(),
|
2019-04-08 17:58:18 -04:00
|
|
|
assoc_ident.span,
|
2020-01-08 08:05:31 -08:00
|
|
|
E0599,
|
|
|
|
"no variant named `{}` found for enum `{}`",
|
|
|
|
assoc_ident,
|
|
|
|
qself_ty,
|
2018-11-24 16:23:11 -08:00
|
|
|
);
|
2019-04-08 17:58:18 -04:00
|
|
|
|
2019-01-10 23:23:30 +03:00
|
|
|
let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
|
|
|
|
if let Some(suggested_name) = find_best_match_for_name(
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
&adt_def
|
2022-03-05 07:28:41 +11:00
|
|
|
.variants()
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
.iter()
|
2022-01-02 22:37:05 -05:00
|
|
|
.map(|variant| variant.name)
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
.collect::<Vec<Symbol>>(),
|
2020-07-08 20:03:37 +10:00
|
|
|
assoc_ident.name,
|
2019-01-10 23:23:30 +03:00
|
|
|
None,
|
|
|
|
) {
|
2019-01-25 16:03:27 -05:00
|
|
|
err.span_suggestion(
|
2019-04-08 17:58:18 -04:00
|
|
|
assoc_ident.span,
|
|
|
|
"there is a variant with a similar name",
|
2022-06-13 15:48:40 +09:00
|
|
|
suggested_name,
|
2019-01-10 23:23:30 +03:00
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
} else {
|
2019-07-19 19:25:03 -07:00
|
|
|
err.span_label(
|
|
|
|
assoc_ident.span,
|
2023-07-25 23:17:39 +02:00
|
|
|
format!("variant not found in `{qself_ty}`"),
|
2019-07-19 19:25:03 -07:00
|
|
|
);
|
2019-04-08 17:58:18 -04:00
|
|
|
}
|
|
|
|
|
2022-07-07 06:52:27 +00:00
|
|
|
if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
|
2023-07-25 23:17:39 +02:00
|
|
|
err.span_label(sp, format!("variant `{assoc_ident}` not found here"));
|
2019-01-10 23:23:30 +03:00
|
|
|
}
|
2019-04-08 17:58:18 -04:00
|
|
|
|
2022-01-22 18:49:12 -06:00
|
|
|
err.emit()
|
2022-11-03 04:57:44 +08:00
|
|
|
} else if let Err(reported) = qself_ty.error_reported() {
|
2022-01-22 18:49:12 -06:00
|
|
|
reported
|
2023-01-08 06:54:52 +00:00
|
|
|
} else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() {
|
|
|
|
// `<impl Trait as OtherTrait>::Assoc` makes no sense.
|
2024-01-04 09:08:36 +11:00
|
|
|
struct_span_code_err!(
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx(),
|
2023-01-08 06:54:52 +00:00
|
|
|
tcx.def_span(alias_ty.def_id),
|
|
|
|
E0667,
|
|
|
|
"`impl Trait` is not allowed in path parameters"
|
|
|
|
)
|
|
|
|
.emit() // Already reported in an earlier stage.
|
2022-01-22 18:49:12 -06:00
|
|
|
} else {
|
2024-02-05 18:53:28 -08:00
|
|
|
self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;
|
2024-02-03 10:37:28 -08:00
|
|
|
|
2023-01-22 05:11:24 +00:00
|
|
|
let traits: Vec<_> =
|
|
|
|
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
|
2023-01-08 06:54:52 +00:00
|
|
|
|
2023-08-01 00:59:59 +00:00
|
|
|
// Don't print `ty::Error` to the user.
|
2024-03-15 03:21:55 +01:00
|
|
|
self.report_ambiguous_assoc_ty(
|
2019-04-17 10:24:50 -07:00
|
|
|
span,
|
2023-01-08 06:54:52 +00:00
|
|
|
&[qself_ty.to_string()],
|
|
|
|
&traits,
|
2019-09-05 11:26:51 +10:00
|
|
|
assoc_ident.name,
|
2022-01-22 18:49:12 -06:00
|
|
|
)
|
|
|
|
};
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(reported);
|
2022-01-22 18:49:12 -06:00
|
|
|
return Err(reported);
|
2015-04-07 17:59:10 +12:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
};
|
2015-02-24 09:24:42 -05:00
|
|
|
|
2018-04-24 21:45:49 -05:00
|
|
|
let trait_did = bound.def_id();
|
2024-03-15 03:21:55 +01:00
|
|
|
let assoc_ty_did = self.probe_assoc_ty(assoc_ident, hir_ref_id, span, trait_did).unwrap();
|
|
|
|
let ty = self.lower_assoc_ty(span, assoc_ty_did, assoc_segment, bound);
|
2017-07-11 10:33:09 -04:00
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
if let Some(variant_def_id) = variant_resolution {
|
2024-05-22 16:46:05 +02:00
|
|
|
tcx.node_span_lint(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
|
|
|
|
lint.primary_message("ambiguous associated item");
|
|
|
|
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
|
|
|
let note_msg = format!(
|
|
|
|
"`{}` could{} refer to the {} defined here",
|
|
|
|
assoc_ident,
|
|
|
|
also,
|
|
|
|
tcx.def_kind_descr(kind, def_id)
|
|
|
|
);
|
|
|
|
lint.span_note(tcx.def_span(def_id), note_msg);
|
|
|
|
};
|
2019-01-10 23:23:30 +03:00
|
|
|
|
2024-05-22 16:46:05 +02:00
|
|
|
could_refer_to(DefKind::Variant, variant_def_id, "");
|
|
|
|
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
|
2020-01-31 22:24:57 +10:00
|
|
|
|
2024-05-22 16:46:05 +02:00
|
|
|
lint.span_suggestion(
|
|
|
|
span,
|
|
|
|
"use fully-qualified syntax",
|
|
|
|
format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
});
|
2019-01-10 23:23:30 +03:00
|
|
|
}
|
2022-11-13 05:12:44 +01:00
|
|
|
Ok((ty, DefKind::AssocTy, assoc_ty_did))
|
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_inherent_assoc_ty(
|
2022-12-08 13:31:21 +01:00
|
|
|
&self,
|
|
|
|
name: Ident,
|
2023-02-01 14:23:51 +00:00
|
|
|
segment: &hir::PathSegment<'tcx>,
|
2022-12-08 13:31:21 +01:00
|
|
|
adt_did: DefId,
|
|
|
|
self_ty: Ty<'tcx>,
|
2024-03-06 17:24:13 +11:00
|
|
|
block: HirId,
|
2022-12-08 13:31:21 +01:00
|
|
|
span: Span,
|
|
|
|
) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
2023-07-03 13:34:54 +02:00
|
|
|
// Don't attempt to look up inherent associated types when the feature is not enabled.
|
|
|
|
// Theoretically it'd be fine to do so since we feature-gate their definition site.
|
|
|
|
// However, due to current limitations of the implementation (caused by us performing
|
2024-02-11 09:22:52 +01:00
|
|
|
// selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
|
|
|
|
// errors (#108491) which mask the feature-gate error, needlessly confusing users
|
|
|
|
// who use IATs by accident (#113265).
|
2023-07-03 13:34:54 +02:00
|
|
|
if !tcx.features().inherent_associated_types {
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
|
2022-12-08 13:31:21 +01:00
|
|
|
let candidates: Vec<_> = tcx
|
2024-01-12 14:29:54 +00:00
|
|
|
.inherent_impls(adt_did)?
|
2022-12-08 13:31:21 +01:00
|
|
|
.iter()
|
2024-03-15 03:21:55 +01:00
|
|
|
.filter_map(|&impl_| Some((impl_, self.probe_assoc_ty_unchecked(name, block, impl_)?)))
|
2022-12-08 13:31:21 +01:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
if candidates.is_empty() {
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
|
2023-03-21 01:46:52 +01:00
|
|
|
//
|
|
|
|
// Select applicable inherent associated type candidates modulo regions.
|
|
|
|
//
|
|
|
|
|
2023-02-17 17:06:27 +01:00
|
|
|
// In contexts that have no inference context, just make a new one.
|
|
|
|
// We do need a local variable to store it, though.
|
|
|
|
let infcx_;
|
|
|
|
let infcx = match self.infcx() {
|
|
|
|
Some(infcx) => infcx,
|
|
|
|
None => {
|
2023-04-27 08:34:11 +01:00
|
|
|
assert!(!self_ty.has_infer());
|
2023-02-17 17:06:27 +01:00
|
|
|
infcx_ = tcx.infer_ctxt().ignoring_regions().build();
|
|
|
|
&infcx_
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-03-21 01:46:52 +01:00
|
|
|
// FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
|
|
|
|
// when inside of an ADT (#108491) or where clause.
|
|
|
|
let param_env = tcx.param_env(block.owner);
|
2023-03-21 01:09:00 +01:00
|
|
|
|
2023-11-20 22:48:08 -03:00
|
|
|
let mut universes = if self_ty.has_escaping_bound_vars() {
|
|
|
|
vec![None; self_ty.outer_exclusive_binder().as_usize()]
|
|
|
|
} else {
|
|
|
|
vec![]
|
|
|
|
};
|
2023-06-10 14:56:08 +02:00
|
|
|
|
2024-02-05 13:40:32 +01:00
|
|
|
let (impl_, (assoc_item, def_scope)) = crate::traits::with_replaced_escaping_bound_vars(
|
|
|
|
infcx,
|
|
|
|
&mut universes,
|
|
|
|
self_ty,
|
|
|
|
|self_ty| {
|
|
|
|
self.select_inherent_assoc_type_candidates(
|
|
|
|
infcx, name, span, self_ty, param_env, candidates,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
)?;
|
2023-11-25 17:48:09 -03:00
|
|
|
|
|
|
|
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
|
|
|
|
|
|
|
|
// FIXME(fmease): Currently creating throwaway `parent_args` to please
|
2024-02-11 09:22:52 +01:00
|
|
|
// `lower_generic_args_of_assoc_item`. Modify the latter instead (or sth. similar) to
|
2023-11-25 17:48:09 -03:00
|
|
|
// not require the parent args logic.
|
|
|
|
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
|
2024-03-15 03:21:55 +01:00
|
|
|
let args = self.lower_generic_args_of_assoc_item(span, assoc_item, segment, parent_args);
|
2023-11-25 17:48:09 -03:00
|
|
|
let args = tcx.mk_args_from_iter(
|
|
|
|
std::iter::once(ty::GenericArg::from(self_ty))
|
|
|
|
.chain(args.into_iter().skip(parent_args.len())),
|
|
|
|
);
|
2023-06-10 14:56:08 +02:00
|
|
|
|
2023-11-25 17:48:09 -03:00
|
|
|
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
|
2023-06-10 14:56:08 +02:00
|
|
|
|
2023-11-25 17:48:09 -03:00
|
|
|
Ok(Some((ty, assoc_item)))
|
2023-11-21 11:19:33 -03:00
|
|
|
}
|
2023-06-10 14:56:08 +02:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
fn select_inherent_assoc_type_candidates(
|
|
|
|
&self,
|
|
|
|
infcx: &InferCtxt<'tcx>,
|
|
|
|
name: Ident,
|
|
|
|
span: Span,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
param_env: ParamEnv<'tcx>,
|
|
|
|
candidates: Vec<(DefId, (DefId, DefId))>,
|
|
|
|
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let mut fulfillment_errors = Vec::new();
|
2022-12-08 13:31:21 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
let applicable_candidates: Vec<_> = candidates
|
|
|
|
.iter()
|
|
|
|
.copied()
|
|
|
|
.filter(|&(impl_, _)| {
|
|
|
|
infcx.probe(|_| {
|
|
|
|
let ocx = ObligationCtxt::new(infcx);
|
2023-11-25 17:48:09 -03:00
|
|
|
let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
|
2023-11-21 11:19:33 -03:00
|
|
|
|
|
|
|
let impl_args = infcx.fresh_args_for_item(span, impl_);
|
|
|
|
let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
|
2023-11-25 17:48:09 -03:00
|
|
|
let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
|
2023-11-21 11:19:33 -03:00
|
|
|
|
|
|
|
// Check that the self types can be related.
|
|
|
|
if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
|
|
|
|
return false;
|
|
|
|
}
|
2022-12-08 13:31:21 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
// Check whether the impl imposes obligations we have to worry about.
|
|
|
|
let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
|
2023-11-25 17:48:09 -03:00
|
|
|
let impl_bounds =
|
|
|
|
ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
|
2023-11-21 11:19:33 -03:00
|
|
|
let impl_obligations = traits::predicates_for_generics(
|
2023-11-25 17:48:09 -03:00
|
|
|
|_, _| ObligationCause::dummy(),
|
2023-11-21 11:19:33 -03:00
|
|
|
param_env,
|
|
|
|
impl_bounds,
|
2023-11-20 22:48:08 -03:00
|
|
|
);
|
2023-11-21 11:19:33 -03:00
|
|
|
ocx.register_obligations(impl_obligations);
|
2023-03-21 01:09:00 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
let mut errors = ocx.select_where_possible();
|
|
|
|
if !errors.is_empty() {
|
|
|
|
fulfillment_errors.append(&mut errors);
|
|
|
|
return false;
|
|
|
|
}
|
2022-12-08 13:31:21 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
true
|
2023-02-17 16:58:18 +01:00
|
|
|
})
|
2023-11-21 11:19:33 -03:00
|
|
|
})
|
|
|
|
.collect();
|
2023-02-17 17:06:27 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
match &applicable_candidates[..] {
|
2024-03-15 03:21:55 +01:00
|
|
|
&[] => Err(self.complain_about_inherent_assoc_ty_not_found(
|
2023-02-17 17:06:27 +01:00
|
|
|
name,
|
2023-11-21 11:19:33 -03:00
|
|
|
self_ty,
|
|
|
|
candidates,
|
|
|
|
fulfillment_errors,
|
2023-02-17 17:06:27 +01:00
|
|
|
span,
|
2023-11-21 11:19:33 -03:00
|
|
|
)),
|
2023-02-17 17:06:27 +01:00
|
|
|
|
2023-11-21 11:19:33 -03:00
|
|
|
&[applicable_candidate] => Ok(applicable_candidate),
|
2023-02-17 18:42:08 +01:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
|
2023-11-21 11:19:33 -03:00
|
|
|
name,
|
|
|
|
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
|
|
|
|
span,
|
|
|
|
)),
|
2022-12-08 13:31:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 17:24:13 +11:00
|
|
|
fn probe_assoc_ty(&self, name: Ident, block: HirId, span: Span, scope: DefId) -> Option<DefId> {
|
2024-03-15 03:21:55 +01:00
|
|
|
let (item, def_scope) = self.probe_assoc_ty_unchecked(name, block, scope)?;
|
2022-12-08 13:31:21 +01:00
|
|
|
self.check_assoc_ty(item, name, def_scope, block, span);
|
|
|
|
Some(item)
|
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn probe_assoc_ty_unchecked(
|
2022-12-08 13:31:21 +01:00
|
|
|
&self,
|
|
|
|
name: Ident,
|
2024-03-06 17:24:13 +11:00
|
|
|
block: HirId,
|
2022-12-08 13:31:21 +01:00
|
|
|
scope: DefId,
|
|
|
|
) -> Option<(DefId, DefId)> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block);
|
|
|
|
|
2023-11-24 09:53:10 +01:00
|
|
|
// We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()`
|
|
|
|
// instead of calling `filter_by_name_and_kind` which would needlessly normalize the
|
|
|
|
// `ident` again and again.
|
2022-12-08 13:31:21 +01:00
|
|
|
let item = tcx.associated_items(scope).in_definition_order().find(|i| {
|
|
|
|
i.kind.namespace() == Namespace::TypeNS
|
|
|
|
&& i.ident(tcx).normalize_to_macros_2_0() == ident
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Some((item.def_id, def_scope))
|
|
|
|
}
|
|
|
|
|
2024-03-06 17:24:13 +11:00
|
|
|
fn check_assoc_ty(&self, item: DefId, name: Ident, def_scope: DefId, block: HirId, span: Span) {
|
2022-12-08 13:31:21 +01:00
|
|
|
let tcx = self.tcx();
|
|
|
|
let kind = DefKind::AssocTy;
|
|
|
|
|
|
|
|
if !tcx.visibility(item).is_accessible_from(def_scope, tcx) {
|
2023-02-21 14:05:32 -07:00
|
|
|
let kind = tcx.def_kind_descr(kind, item);
|
2022-12-08 13:31:21 +01:00
|
|
|
let msg = format!("{kind} `{name}` is private");
|
|
|
|
let def_span = tcx.def_span(item);
|
2024-01-10 14:58:03 +00:00
|
|
|
let reported = tcx
|
|
|
|
.dcx()
|
2024-01-03 21:50:36 +11:00
|
|
|
.struct_span_err(span, msg)
|
Stop using `String` for error codes.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
2024-01-14 10:57:07 +11:00
|
|
|
.with_code(E0624)
|
2024-01-09 09:08:49 +11:00
|
|
|
.with_span_label(span, format!("private {kind}"))
|
|
|
|
.with_span_label(def_span, format!("{kind} defined here"))
|
2022-12-08 13:31:21 +01:00
|
|
|
.emit();
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(reported);
|
2022-12-08 13:31:21 +01:00
|
|
|
}
|
|
|
|
tcx.check_stability(item, Some(block), span, None);
|
|
|
|
}
|
|
|
|
|
2023-01-22 05:11:24 +00:00
|
|
|
fn probe_traits_that_match_assoc_ty(
|
|
|
|
&self,
|
|
|
|
qself_ty: Ty<'tcx>,
|
|
|
|
assoc_ident: Ident,
|
|
|
|
) -> Vec<String> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
// In contexts that have no inference context, just make a new one.
|
|
|
|
// We do need a local variable to store it, though.
|
|
|
|
let infcx_;
|
|
|
|
let infcx = if let Some(infcx) = self.infcx() {
|
|
|
|
infcx
|
|
|
|
} else {
|
2023-04-27 08:34:11 +01:00
|
|
|
assert!(!qself_ty.has_infer());
|
2023-01-22 05:11:24 +00:00
|
|
|
infcx_ = tcx.infer_ctxt().build();
|
|
|
|
&infcx_
|
|
|
|
};
|
|
|
|
|
|
|
|
tcx.all_traits()
|
|
|
|
.filter(|trait_def_id| {
|
|
|
|
// Consider only traits with the associated type
|
|
|
|
tcx.associated_items(*trait_def_id)
|
|
|
|
.in_definition_order()
|
|
|
|
.any(|i| {
|
|
|
|
i.kind.namespace() == Namespace::TypeNS
|
|
|
|
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
|
|
|
|
&& matches!(i.kind, ty::AssocKind::Type)
|
|
|
|
})
|
|
|
|
// Consider only accessible traits
|
|
|
|
&& tcx.visibility(*trait_def_id)
|
|
|
|
.is_accessible_from(self.item_def_id(), tcx)
|
|
|
|
&& tcx.all_impls(*trait_def_id)
|
|
|
|
.any(|impl_def_id| {
|
2024-02-10 22:27:03 +00:00
|
|
|
let impl_header = tcx.impl_trait_header(impl_def_id);
|
|
|
|
impl_header.is_some_and(|header| {
|
2024-03-05 20:19:05 +01:00
|
|
|
let trait_ref = header.trait_ref.instantiate(
|
2023-01-22 05:11:24 +00:00
|
|
|
tcx,
|
2023-07-11 22:35:29 +01:00
|
|
|
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
|
2023-01-22 05:11:24 +00:00
|
|
|
);
|
2024-03-05 20:19:05 +01:00
|
|
|
|
2023-04-11 17:17:25 +00:00
|
|
|
let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
|
|
|
|
// FIXME: Don't bother dealing with non-lifetime binders here...
|
|
|
|
if value.has_escaping_bound_vars() {
|
|
|
|
return false;
|
|
|
|
}
|
2023-01-22 05:11:24 +00:00
|
|
|
infcx
|
|
|
|
.can_eq(
|
|
|
|
ty::ParamEnv::empty(),
|
2024-03-05 20:19:05 +01:00
|
|
|
trait_ref.self_ty(),
|
2023-04-11 17:17:25 +00:00
|
|
|
value,
|
2024-02-10 22:27:03 +00:00
|
|
|
) && header.polarity != ty::ImplPolarity::Negative
|
2023-01-22 05:11:24 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a qualified path to a type.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all)]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_qpath(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
opt_self_ty: Option<Ty<'tcx>>,
|
|
|
|
item_def_id: DefId,
|
2023-02-01 14:23:51 +00:00
|
|
|
trait_segment: &hir::PathSegment<'tcx>,
|
|
|
|
item_segment: &hir::PathSegment<'tcx>,
|
2022-10-20 09:39:09 +00:00
|
|
|
constness: ty::BoundConstness,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> Ty<'tcx> {
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2022-04-25 22:08:45 +03:00
|
|
|
let trait_def_id = tcx.parent(item_def_id);
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?trait_def_id);
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2021-10-16 03:45:14 +02:00
|
|
|
let Some(self_ty) = opt_self_ty else {
|
2018-12-19 12:31:35 +02:00
|
|
|
let path_str = tcx.def_path_str(trait_def_id);
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2019-11-02 09:49:05 +01:00
|
|
|
let def_id = self.item_def_id();
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(item_def_id = ?def_id);
|
2019-11-02 09:49:05 +01:00
|
|
|
|
2022-10-31 16:19:36 +00:00
|
|
|
let parent_def_id = def_id
|
|
|
|
.as_local()
|
2023-11-24 19:28:19 +03:00
|
|
|
.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
|
2021-10-21 19:41:47 +02:00
|
|
|
.map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?parent_def_id);
|
2019-11-02 09:49:05 +01:00
|
|
|
|
2019-11-01 13:50:36 +01:00
|
|
|
// If the trait in segment is the same as the trait defining the item,
|
|
|
|
// use the `<Self as ..>` syntax in the error.
|
2022-10-31 16:19:36 +00:00
|
|
|
let is_part_of_self_trait_constraints = def_id == trait_def_id;
|
2019-11-02 09:49:05 +01:00
|
|
|
let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2023-01-08 06:54:52 +00:00
|
|
|
let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
|
|
|
|
vec!["Self".to_string()]
|
2019-11-01 13:50:36 +01:00
|
|
|
} else {
|
2023-01-08 06:54:52 +00:00
|
|
|
// Find all the types that have an `impl` for the trait.
|
|
|
|
tcx.all_impls(trait_def_id)
|
2024-02-10 22:27:03 +00:00
|
|
|
.filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
|
|
|
|
.filter(|header| {
|
2023-01-08 06:54:52 +00:00
|
|
|
// Consider only accessible traits
|
2023-03-29 22:15:38 +04:00
|
|
|
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
|
2024-03-05 20:19:05 +01:00
|
|
|
&& header.polarity != ty::ImplPolarity::Negative
|
2023-01-08 06:54:52 +00:00
|
|
|
})
|
2024-03-05 20:19:05 +01:00
|
|
|
.map(|header| header.trait_ref.instantiate_identity().self_ty())
|
2023-01-08 06:54:52 +00:00
|
|
|
// We don't care about blanket impls.
|
2023-01-08 07:24:36 +00:00
|
|
|
.filter(|self_ty| !self_ty.has_non_region_param())
|
2023-01-08 06:54:52 +00:00
|
|
|
.map(|self_ty| tcx.erase_regions(self_ty).to_string())
|
|
|
|
.collect()
|
2019-11-01 13:50:36 +01:00
|
|
|
};
|
2023-01-08 06:54:52 +00:00
|
|
|
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
|
|
|
|
// references the trait. Relevant for the first case in
|
|
|
|
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
|
2024-03-15 03:21:55 +01:00
|
|
|
let reported = self.report_ambiguous_assoc_ty(
|
2019-04-17 10:24:50 -07:00
|
|
|
span,
|
2023-01-08 06:54:52 +00:00
|
|
|
&type_names,
|
|
|
|
&[path_str],
|
2019-09-05 11:26:51 +10:00
|
|
|
item_segment.ident.name,
|
2019-04-17 10:24:50 -07:00
|
|
|
);
|
2023-07-05 20:13:26 +01:00
|
|
|
return Ty::new_error(tcx, reported);
|
2016-05-11 08:48:12 +03:00
|
|
|
};
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?self_ty);
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let trait_ref =
|
|
|
|
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false, constness);
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?trait_ref);
|
2014-11-08 06:59:10 -05:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let item_args =
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
|
2019-12-08 17:04:17 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
Ty::new_projection(tcx, item_def_id, item_args)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn prohibit_generic_args<'a>(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2022-05-27 19:53:31 -07:00
|
|
|
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
2024-03-22 14:20:31 +08:00
|
|
|
err_extend: GenericsArgsErrExtend<'_>,
|
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
|
|
|
let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
|
|
|
|
let mut result = Ok(());
|
|
|
|
if let Some(_) = args_visitors.clone().next() {
|
|
|
|
result = Err(self.report_prohibit_generics_error(
|
|
|
|
segments.clone(),
|
|
|
|
args_visitors,
|
|
|
|
err_extend,
|
|
|
|
));
|
2022-05-27 15:20:21 -07:00
|
|
|
}
|
2020-02-24 15:50:40 +01:00
|
|
|
|
2022-05-27 15:20:21 -07:00
|
|
|
for segment in segments {
|
2020-02-24 15:50:40 +01:00
|
|
|
// Only emit the first error to avoid overloading the user with error messages.
|
2024-05-27 23:53:46 +02:00
|
|
|
if let Some(c) = segment.args().constraints.first() {
|
|
|
|
return Err(prohibit_assoc_item_constraint(self.tcx(), c, None));
|
2019-06-12 11:42:58 +03:00
|
|
|
}
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
2024-03-22 14:20:31 +08:00
|
|
|
|
|
|
|
result
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Probe path segments that are semantically allowed to have generic arguments.
|
|
|
|
///
|
|
|
|
/// ### Example
|
|
|
|
///
|
|
|
|
/// ```ignore (illustrative)
|
|
|
|
/// Option::None::<()>
|
|
|
|
/// // ^^^^ permitted to have generic args
|
|
|
|
///
|
|
|
|
/// // ==> [GenericPathSegment(Option_def_id, 1)]
|
|
|
|
///
|
|
|
|
/// Option::<()>::None
|
|
|
|
/// // ^^^^^^ ^^^^ *not* permitted to have generic args
|
|
|
|
/// // permitted to have generic args
|
|
|
|
///
|
|
|
|
/// // ==> [GenericPathSegment(Option_def_id, 0)]
|
|
|
|
/// ```
|
2019-04-20 19:46:19 +03:00
|
|
|
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn probe_generic_path_segments(
|
2019-04-20 19:46:19 +03:00
|
|
|
&self,
|
2019-12-01 16:08:58 +01:00
|
|
|
segments: &[hir::PathSegment<'_>],
|
2019-04-20 19:46:19 +03:00
|
|
|
self_ty: Option<Ty<'tcx>>,
|
|
|
|
kind: DefKind,
|
|
|
|
def_id: DefId,
|
2022-10-29 16:19:57 +03:00
|
|
|
span: Span,
|
2024-03-15 03:21:55 +01:00
|
|
|
) -> Vec<GenericPathSegment> {
|
2024-02-11 09:22:52 +01:00
|
|
|
// We need to extract the generic arguments supplied by the user in
|
2018-12-18 18:59:00 +00:00
|
|
|
// the path `path`. Due to the current setup, this is a bit of a
|
2024-02-11 09:22:52 +01:00
|
|
|
// tricky process; the problem is that resolve only tells us the
|
2018-12-18 18:59:00 +00:00
|
|
|
// end-point of the path resolution, and not the intermediate steps.
|
|
|
|
// Luckily, we can (at least for now) deduce the intermediate steps
|
|
|
|
// just from the end-point.
|
|
|
|
//
|
|
|
|
// There are basically five cases to consider:
|
|
|
|
//
|
|
|
|
// 1. Reference to a constructor of a struct:
|
|
|
|
//
|
|
|
|
// struct Foo<T>(...)
|
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// In this case, the generic arguments are declared in the type space.
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
|
|
|
// 2. Reference to a constructor of an enum variant:
|
|
|
|
//
|
|
|
|
// enum E<T> { Foo(...) }
|
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// In this case, the generic arguments are defined in the type space,
|
2018-12-18 18:59:00 +00:00
|
|
|
// but may be specified either on the type or the variant.
|
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// 3. Reference to a free function or constant:
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// fn foo<T>() {}
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
|
|
|
// In this case, the path will again always have the form
|
2024-02-11 09:22:52 +01:00
|
|
|
// `a::b::foo::<T>` where only the final segment should have generic
|
|
|
|
// arguments. However, in this case, those arguments are declared on
|
|
|
|
// a value, and hence are in the value space.
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// 4. Reference to an associated function or constant:
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
|
|
|
// impl<A> SomeStruct<A> {
|
2024-02-11 09:22:52 +01:00
|
|
|
// fn foo<B>(...) {}
|
2018-12-18 18:59:00 +00:00
|
|
|
// }
|
|
|
|
//
|
2024-02-11 09:22:52 +01:00
|
|
|
// Here we can have a path like `a::b::SomeStruct::<A>::foo::<B>`,
|
|
|
|
// in which case generic arguments may appear in two places. The
|
|
|
|
// penultimate segment, `SomeStruct::<A>`, contains generic arguments
|
|
|
|
// in the type space, and the final segment, `foo::<B>` contains
|
|
|
|
// generic arguments in value space.
|
2018-12-18 18:59:00 +00:00
|
|
|
//
|
|
|
|
// The first step then is to categorize the segments appropriately.
|
|
|
|
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
assert!(!segments.is_empty());
|
|
|
|
let last = segments.len() - 1;
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let mut generic_segments = vec![];
|
2018-12-18 18:59:00 +00:00
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
match kind {
|
2018-12-18 18:59:00 +00:00
|
|
|
// Case 1. Reference to a struct constructor.
|
2019-04-20 19:46:19 +03:00
|
|
|
DefKind::Ctor(CtorOf::Struct, ..) => {
|
2018-12-18 18:59:00 +00:00
|
|
|
// Everything but the final segment should have no
|
|
|
|
// parameters at all.
|
|
|
|
let generics = tcx.generics_of(def_id);
|
|
|
|
// Variant and struct constructors use the
|
|
|
|
// generics of their parent type definition.
|
|
|
|
let generics_def_id = generics.parent.unwrap_or(def_id);
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments.push(GenericPathSegment(generics_def_id, last));
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Case 2. Reference to a variant constructor.
|
2019-12-24 17:38:22 -05:00
|
|
|
DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
|
2022-10-29 16:19:57 +03:00
|
|
|
let (generics_def_id, index) = if let Some(self_ty) = self_ty {
|
|
|
|
let adt_def = self.probe_adt(span, self_ty).unwrap();
|
2018-12-18 18:59:00 +00:00
|
|
|
debug_assert!(adt_def.is_enum());
|
2022-03-05 07:28:41 +11:00
|
|
|
(adt_def.did(), last)
|
2018-12-18 18:59:00 +00:00
|
|
|
} else if last >= 1 && segments[last - 1].args.is_some() {
|
|
|
|
// Everything but the penultimate segment should have no
|
|
|
|
// parameters at all.
|
2019-03-21 23:38:50 +01:00
|
|
|
let mut def_id = def_id;
|
|
|
|
|
2019-04-20 18:26:26 +03:00
|
|
|
// `DefKind::Ctor` -> `DefKind::Variant`
|
2019-04-20 19:46:19 +03:00
|
|
|
if let DefKind::Ctor(..) = kind {
|
2022-04-25 22:08:45 +03:00
|
|
|
def_id = tcx.parent(def_id);
|
2019-03-21 23:38:50 +01:00
|
|
|
}
|
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
// `DefKind::Variant` -> `DefKind::Enum`
|
2022-04-25 22:08:45 +03:00
|
|
|
let enum_def_id = tcx.parent(def_id);
|
2018-12-18 18:59:00 +00:00
|
|
|
(enum_def_id, last - 1)
|
|
|
|
} else {
|
|
|
|
// FIXME: lint here recommending `Enum::<...>::Variant` form
|
|
|
|
// instead of `Enum::Variant::<...>` form.
|
|
|
|
|
|
|
|
// Everything but the final segment should have no
|
|
|
|
// parameters at all.
|
|
|
|
let generics = tcx.generics_of(def_id);
|
|
|
|
// Variant and struct constructors use the
|
|
|
|
// generics of their parent type definition.
|
|
|
|
(generics.parent.unwrap_or(def_id), last)
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments.push(GenericPathSegment(generics_def_id, index));
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Case 3. Reference to a top-level value.
|
2024-02-23 23:12:20 +00:00
|
|
|
DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } => {
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments.push(GenericPathSegment(def_id, last));
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Case 4. Reference to a method or associated const.
|
2020-03-03 12:29:07 -06:00
|
|
|
DefKind::AssocFn | DefKind::AssocConst => {
|
2018-12-18 18:59:00 +00:00
|
|
|
if segments.len() >= 2 {
|
|
|
|
let generics = tcx.generics_of(def_id);
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments.push(GenericPathSegment(generics.parent.unwrap(), last - 1));
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments.push(GenericPathSegment(def_id, last));
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?generic_segments);
|
2018-12-18 18:59:00 +00:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
generic_segments
|
2018-12-18 18:59:00 +00:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a type `Path` to a type.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_path(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
|
|
|
opt_self_ty: Option<Ty<'tcx>>,
|
2023-02-01 14:23:51 +00:00
|
|
|
path: &hir::Path<'tcx>,
|
2024-03-06 17:24:13 +11:00
|
|
|
hir_id: HirId,
|
2019-12-24 17:38:22 -05:00
|
|
|
permit_variants: bool,
|
|
|
|
) -> Ty<'tcx> {
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?path.res, ?opt_self_ty, ?path.segments);
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
|
|
|
|
2016-11-25 13:21:19 +02:00
|
|
|
let span = path.span;
|
2019-04-20 19:36:05 +03:00
|
|
|
match path.res {
|
2023-06-24 00:00:08 -03:00
|
|
|
Res::Def(DefKind::OpaqueTy, did) => {
|
2019-02-28 22:43:53 +00:00
|
|
|
// Check for desugared `impl Trait`.
|
2023-01-18 18:03:06 +00:00
|
|
|
assert!(tcx.is_type_alias_impl_trait(did));
|
2018-07-03 19:38:14 +02:00
|
|
|
let item_segment = path.segments.split_last().unwrap();
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self
|
|
|
|
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
|
2024-03-15 03:21:55 +01:00
|
|
|
let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0);
|
2023-07-11 22:35:29 +01:00
|
|
|
Ty::new_opaque(tcx, did, args)
|
2018-07-03 19:38:14 +02:00
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
Res::Def(
|
|
|
|
DefKind::Enum
|
2023-09-26 02:15:32 +00:00
|
|
|
| DefKind::TyAlias
|
2020-04-16 17:38:52 -07:00
|
|
|
| DefKind::Struct
|
|
|
|
| DefKind::Union
|
|
|
|
| DefKind::ForeignTy,
|
|
|
|
did,
|
|
|
|
) => {
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.split_last().unwrap().1.iter(),
|
|
|
|
GenericsArgsErrExtend::None,
|
|
|
|
);
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_path_segment(span, did, path.segments.last().unwrap())
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
|
2024-02-11 09:22:52 +01:00
|
|
|
// Lower "variant type" as if it were a real type.
|
2016-09-15 00:51:46 +03:00
|
|
|
// The resulting `Ty` is type of the variant's enum for now.
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2018-12-18 18:59:00 +00:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let generic_segments =
|
|
|
|
self.probe_generic_path_segments(path.segments, None, kind, def_id, span);
|
|
|
|
let indices: FxHashSet<_> =
|
|
|
|
generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect();
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
2022-05-27 19:53:31 -07:00
|
|
|
path.segments.iter().enumerate().filter_map(|(index, seg)| {
|
2024-03-15 03:21:55 +01:00
|
|
|
if !indices.contains(&index) { Some(seg) } else { None }
|
2022-05-27 19:53:31 -07:00
|
|
|
}),
|
2024-03-22 14:20:31 +08:00
|
|
|
GenericsArgsErrExtend::DefVariant,
|
2022-05-27 19:53:31 -07:00
|
|
|
);
|
2018-12-18 18:59:00 +00:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
|
|
|
self.lower_path_segment(span, *def_id, &path.segments[*index])
|
2016-09-15 00:51:46 +03:00
|
|
|
}
|
2019-05-25 10:12:30 +01:00
|
|
|
Res::Def(DefKind::TyParam, def_id) => {
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.iter(),
|
2024-05-11 15:40:34 +02:00
|
|
|
GenericsArgsErrExtend::Param(def_id),
|
2024-03-22 14:20:31 +08:00
|
|
|
);
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_ty_param(hir_id)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2022-09-16 11:45:33 +10:00
|
|
|
Res::SelfTyParam { .. } => {
|
2019-03-17 15:26:01 +00:00
|
|
|
// `Self` in trait or type alias.
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.iter(),
|
2023-02-16 00:06:51 +01:00
|
|
|
if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments {
|
2024-03-22 14:20:31 +08:00
|
|
|
GenericsArgsErrExtend::SelfTyParam(
|
2022-05-27 19:53:31 -07:00
|
|
|
ident.span.shrink_to_hi().to(args.span_ext),
|
2024-03-22 14:20:31 +08:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
GenericsArgsErrExtend::None
|
|
|
|
},
|
|
|
|
);
|
2019-08-12 22:15:12 +01:00
|
|
|
tcx.types.self_param
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2022-09-16 11:45:33 +10:00
|
|
|
Res::SelfTyAlias { alias_to: def_id, forbid_generic, .. } => {
|
2019-02-28 22:43:53 +00:00
|
|
|
// `Self` in impl (we know the concrete type).
|
|
|
|
assert_eq!(opt_self_ty, None);
|
|
|
|
// Try to evaluate any array length constants.
|
2023-07-11 22:35:29 +01:00
|
|
|
let ty = tcx.at(span).type_of(def_id).instantiate_identity();
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.iter(),
|
|
|
|
GenericsArgsErrExtend::SelfTyAlias { def_id, span },
|
|
|
|
);
|
2022-02-09 12:29:43 +01:00
|
|
|
// HACK(min_const_generics): Forbid generic `Self` types
|
|
|
|
// here as we can't easily do that during nameres.
|
|
|
|
//
|
|
|
|
// We do this before normalization as we otherwise allow
|
|
|
|
// ```rust
|
|
|
|
// trait AlwaysApplicable { type Assoc; }
|
|
|
|
// impl<T: ?Sized> AlwaysApplicable for T { type Assoc = usize; }
|
|
|
|
//
|
|
|
|
// trait BindsParam<T> {
|
|
|
|
// type ArrayTy;
|
|
|
|
// }
|
|
|
|
// impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc {
|
|
|
|
// type ArrayTy = [u8; Self::MAX];
|
|
|
|
// }
|
|
|
|
// ```
|
|
|
|
// Note that the normalization happens in the param env of
|
|
|
|
// the anon const, which is empty. This is why the
|
|
|
|
// `AlwaysApplicable` impl needs a `T: ?Sized` bound for
|
|
|
|
// this to compile if we were to normalize here.
|
2023-04-27 07:52:17 +01:00
|
|
|
if forbid_generic && ty.has_param() {
|
2023-12-18 22:21:37 +11:00
|
|
|
let mut err = tcx.dcx().struct_span_err(
|
2020-09-08 11:37:27 +02:00
|
|
|
path.span,
|
|
|
|
"generic `Self` types are currently not permitted in anonymous constants",
|
|
|
|
);
|
|
|
|
if let Some(hir::Node::Item(&hir::Item {
|
2023-01-09 16:30:40 +00:00
|
|
|
kind: hir::ItemKind::Impl(impl_),
|
2020-09-08 11:37:27 +02:00
|
|
|
..
|
|
|
|
})) = tcx.hir().get_if_local(def_id)
|
|
|
|
{
|
2020-11-22 17:46:21 -05:00
|
|
|
err.span_note(impl_.self_ty.span, "not a concrete type");
|
2020-09-08 11:37:27 +02:00
|
|
|
}
|
2024-01-10 14:58:03 +00:00
|
|
|
let reported = err.emit();
|
|
|
|
self.set_tainted_by_errors(reported);
|
|
|
|
Ty::new_error(tcx, reported)
|
2020-09-01 14:30:16 +02:00
|
|
|
} else {
|
2022-09-17 21:35:47 +03:00
|
|
|
ty
|
2020-09-01 14:30:16 +02:00
|
|
|
}
|
2019-02-28 22:43:53 +00:00
|
|
|
}
|
2019-05-19 16:26:08 +08:00
|
|
|
Res::Def(DefKind::AssocTy, def_id) => {
|
2018-12-26 00:07:31 +00:00
|
|
|
debug_assert!(path.segments.len() >= 2);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments[..path.segments.len() - 2].iter(),
|
|
|
|
GenericsArgsErrExtend::None,
|
|
|
|
);
|
2022-10-20 09:39:09 +00:00
|
|
|
// HACK: until we support `<Type as ~const Trait>`, assume all of them are.
|
|
|
|
let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) {
|
|
|
|
ty::BoundConstness::ConstIfConst
|
|
|
|
} else {
|
|
|
|
ty::BoundConstness::NotConst
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_qpath(
|
2019-12-24 17:38:22 -05:00
|
|
|
span,
|
|
|
|
opt_self_ty,
|
|
|
|
def_id,
|
|
|
|
&path.segments[path.segments.len() - 2],
|
|
|
|
path.segments.last().unwrap(),
|
2022-10-20 09:39:09 +00:00
|
|
|
constness,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::PrimTy(prim_ty) => {
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2024-03-22 14:20:31 +08:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.iter(),
|
|
|
|
GenericsArgsErrExtend::PrimTy(prim_ty),
|
|
|
|
);
|
2017-02-15 15:00:20 +02:00
|
|
|
match prim_ty {
|
2020-01-05 01:50:05 +01:00
|
|
|
hir::PrimTy::Bool => tcx.types.bool,
|
|
|
|
hir::PrimTy::Char => tcx.types.char,
|
2023-07-05 20:13:26 +01:00
|
|
|
hir::PrimTy::Int(it) => Ty::new_int(tcx, ty::int_ty(it)),
|
|
|
|
hir::PrimTy::Uint(uit) => Ty::new_uint(tcx, ty::uint_ty(uit)),
|
|
|
|
hir::PrimTy::Float(ft) => Ty::new_float(tcx, ty::float_ty(ft)),
|
2020-05-28 13:02:02 +02:00
|
|
|
hir::PrimTy::Str => tcx.types.str_,
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Err => {
|
2022-11-18 11:30:21 +00:00
|
|
|
let e = self
|
|
|
|
.tcx()
|
2023-12-18 22:21:37 +11:00
|
|
|
.dcx()
|
2023-11-30 15:01:11 +11:00
|
|
|
.span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
|
2022-11-18 11:30:21 +00:00
|
|
|
self.set_tainted_by_errors(e);
|
2023-07-05 20:13:26 +01:00
|
|
|
Ty::new_error(self.tcx(), e)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2024-04-15 21:00:49 -04:00
|
|
|
Res::Def(..) => {
|
|
|
|
assert_eq!(
|
|
|
|
path.segments.get(0).map(|seg| seg.ident.name),
|
|
|
|
Some(kw::SelfUpper),
|
|
|
|
"only expected incorrect resolution for `Self`"
|
|
|
|
);
|
|
|
|
Ty::new_error(
|
|
|
|
self.tcx(),
|
|
|
|
self.tcx().dcx().span_delayed_bug(span, "incorrect resolution for `Self`"),
|
|
|
|
)
|
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => span_bug!(span, "unexpected resolution: {:?}", path.res),
|
2015-02-11 09:33:49 +02:00
|
|
|
}
|
2015-04-03 17:13:52 +13:00
|
|
|
}
|
2015-02-11 09:33:49 +02:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a type parameter from the HIR to our internal notion of a type.
|
|
|
|
///
|
|
|
|
/// Early-bound type parameters get lowered to [`ty::Param`]
|
|
|
|
/// and late-bound ones to [`ty::Bound`].
|
2024-03-06 17:24:13 +11:00
|
|
|
pub(crate) fn lower_ty_param(&self, hir_id: HirId) -> Ty<'tcx> {
|
2023-08-29 21:50:01 +00:00
|
|
|
let tcx = self.tcx();
|
|
|
|
match tcx.named_bound_var(hir_id) {
|
|
|
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
|
|
|
|
let name = tcx.item_name(def_id);
|
|
|
|
let br = ty::BoundTy {
|
|
|
|
var: ty::BoundVar::from_u32(index),
|
|
|
|
kind: ty::BoundTyKind::Param(def_id, name),
|
|
|
|
};
|
|
|
|
Ty::new_bound(tcx, debruijn, br)
|
|
|
|
}
|
|
|
|
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
|
|
|
let def_id = def_id.expect_local();
|
|
|
|
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
|
|
|
let generics = tcx.generics_of(item_def_id);
|
|
|
|
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
|
|
|
|
Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
|
|
|
|
}
|
|
|
|
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
|
|
|
|
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a const parameter from the HIR to our internal notion of a constant.
|
|
|
|
///
|
|
|
|
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
|
|
|
|
/// and late-bound ones to [`ty::ConstKind::Bound`].
|
2024-03-06 17:24:13 +11:00
|
|
|
pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
|
2023-08-29 21:50:01 +00:00
|
|
|
let tcx = self.tcx();
|
|
|
|
match tcx.named_bound_var(hir_id) {
|
|
|
|
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
|
|
|
// Find the name and index of the const parameter by indexing the generics of
|
|
|
|
// the parent item and construct a `ParamConst`.
|
|
|
|
let item_def_id = tcx.parent(def_id);
|
|
|
|
let generics = tcx.generics_of(item_def_id);
|
|
|
|
let index = generics.param_def_id_to_index[&def_id];
|
|
|
|
let name = tcx.item_name(def_id);
|
|
|
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)
|
|
|
|
}
|
|
|
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
|
|
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty)
|
|
|
|
}
|
|
|
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty),
|
|
|
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a type from the HIR to our internal notion of a type.
|
2024-02-11 09:24:35 +01:00
|
|
|
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
|
|
|
self.lower_ty_common(hir_ty, false, false)
|
2021-07-10 10:00:54 +02:00
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a type inside of a path from the HIR to our internal notion of a type.
|
2024-02-11 09:24:35 +01:00
|
|
|
pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
|
|
|
self.lower_ty_common(hir_ty, false, true)
|
2020-08-13 18:30:00 -07:00
|
|
|
}
|
|
|
|
|
2023-11-26 15:57:31 +03:00
|
|
|
fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
|
|
|
|
let mut error_occured = false;
|
|
|
|
let sig_span = self.tcx().def_span(sig_id);
|
|
|
|
let mut try_emit = |descr| {
|
|
|
|
if emit {
|
|
|
|
self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation {
|
|
|
|
span,
|
|
|
|
descr,
|
|
|
|
callee_span: sig_span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
error_occured = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(node) = self.tcx().hir().get_if_local(sig_id)
|
|
|
|
&& let Some(decl) = node.fn_decl()
|
|
|
|
&& let hir::FnRetTy::Return(ty) = decl.output
|
|
|
|
&& let hir::TyKind::InferDelegation(_, _) = ty.kind
|
|
|
|
{
|
|
|
|
try_emit("recursive delegation");
|
|
|
|
}
|
|
|
|
|
|
|
|
let sig_generics = self.tcx().generics_of(sig_id);
|
|
|
|
let parent = self.tcx().parent(self.item_def_id());
|
|
|
|
let parent_generics = self.tcx().generics_of(parent);
|
|
|
|
|
|
|
|
let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
|
|
|
|
let sig_has_self = sig_generics.has_self as usize;
|
|
|
|
|
|
|
|
if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
|
|
|
|
try_emit("delegation with early bound generics");
|
|
|
|
}
|
|
|
|
|
2024-03-26 18:59:03 +03:00
|
|
|
// There is no way to instantiate `Self` param for caller if
|
|
|
|
// 1. callee is a trait method
|
|
|
|
// 2. delegation item isn't an associative item
|
|
|
|
if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
|
|
|
|
&& let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
|
|
|
|
&& self.tcx().associated_item(sig_id).container
|
|
|
|
== ty::AssocItemContainer::TraitContainer
|
|
|
|
{
|
|
|
|
try_emit("delegation to a trait method from a free function");
|
|
|
|
}
|
|
|
|
|
2023-11-26 15:57:31 +03:00
|
|
|
error_occured
|
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_delegation_ty(
|
2023-11-26 15:57:31 +03:00
|
|
|
&self,
|
|
|
|
sig_id: DefId,
|
|
|
|
idx: hir::InferDelegationKind,
|
|
|
|
span: Span,
|
|
|
|
) -> Ty<'tcx> {
|
|
|
|
if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
|
|
|
|
{
|
|
|
|
let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case");
|
|
|
|
self.set_tainted_by_errors(e);
|
|
|
|
return Ty::new_error(self.tcx(), e);
|
|
|
|
};
|
|
|
|
let sig = self.tcx().fn_sig(sig_id);
|
|
|
|
let sig_generics = self.tcx().generics_of(sig_id);
|
|
|
|
|
|
|
|
let parent = self.tcx().parent(self.item_def_id());
|
|
|
|
let parent_def_kind = self.tcx().def_kind(parent);
|
|
|
|
|
|
|
|
let sig = if let DefKind::Impl { .. } = parent_def_kind
|
|
|
|
&& sig_generics.has_self
|
|
|
|
{
|
|
|
|
// Generic params can't be here except the trait self type.
|
|
|
|
// They are not supported yet.
|
|
|
|
assert_eq!(sig_generics.count(), 1);
|
|
|
|
assert_eq!(self.tcx().generics_of(parent).count(), 0);
|
|
|
|
|
|
|
|
let self_ty = self.tcx().type_of(parent).instantiate_identity();
|
|
|
|
let generic_self_ty = ty::GenericArg::from(self_ty);
|
2024-02-12 15:39:32 +09:00
|
|
|
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
|
|
|
sig.instantiate(self.tcx(), args)
|
2023-11-26 15:57:31 +03:00
|
|
|
} else {
|
|
|
|
sig.instantiate_identity()
|
|
|
|
};
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
// Bound vars are also inherited from `sig_id`.
|
|
|
|
// They will be rebound later in `lower_fn_ty`.
|
2023-11-26 15:57:31 +03:00
|
|
|
let sig = sig.skip_binder();
|
|
|
|
|
|
|
|
match idx {
|
|
|
|
hir::InferDelegationKind::Input(id) => sig.inputs()[id],
|
|
|
|
hir::InferDelegationKind::Output => sig.output(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a type from the HIR to our internal notion of a type given some extra data for diagnostics.
|
|
|
|
///
|
|
|
|
/// Extra diagnostic data:
|
|
|
|
///
|
|
|
|
/// 1. `borrowed`: Whether trait object types are borrowed like in `&dyn Trait`.
|
|
|
|
/// Used to avoid emitting redundant errors.
|
|
|
|
/// 2. `in_path`: Whether the type appears inside of a path.
|
|
|
|
/// Used to provide correct diagnostics for bare trait object types.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2024-02-11 09:24:35 +01:00
|
|
|
fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> {
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
let result_ty = match &hir_ty.kind {
|
2023-11-26 15:57:31 +03:00
|
|
|
hir::TyKind::InferDelegation(sig_id, idx) => {
|
2024-02-11 09:24:35 +01:00
|
|
|
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
|
2023-11-26 15:57:31 +03:00
|
|
|
}
|
2024-03-15 03:21:55 +01:00
|
|
|
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
|
2024-03-21 17:07:52 -04:00
|
|
|
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Ref(region, mt) => {
|
2024-03-15 03:21:55 +01:00
|
|
|
let r = self.lower_lifetime(region, None);
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?r);
|
2024-03-15 03:21:55 +01:00
|
|
|
let t = self.lower_ty_common(mt.ty, true, false);
|
2024-03-21 17:07:52 -04:00
|
|
|
Ty::new_ref(tcx, r, t, mt.mutbl)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
hir::TyKind::Never => tcx.types.never,
|
2023-02-17 14:33:08 +11:00
|
|
|
hir::TyKind::Tup(fields) => {
|
2024-03-15 03:21:55 +01:00
|
|
|
Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t)))
|
2023-02-17 14:33:08 +11:00
|
|
|
}
|
2024-01-04 21:53:06 +08:00
|
|
|
hir::TyKind::AnonAdt(item_id) => {
|
2024-02-11 09:24:35 +01:00
|
|
|
let _guard = debug_span!("AnonAdt");
|
|
|
|
|
2024-01-04 21:53:06 +08:00
|
|
|
let did = item_id.owner_id.def_id;
|
|
|
|
let adt_def = tcx.adt_def(did);
|
|
|
|
|
|
|
|
let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| {
|
|
|
|
tcx.mk_param_from_def(param)
|
|
|
|
});
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?args);
|
2024-01-04 21:53:06 +08:00
|
|
|
|
|
|
|
Ty::new_adt(tcx, adt_def, tcx.mk_args(args))
|
|
|
|
}
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::TyKind::BareFn(bf) => {
|
2024-02-11 09:24:35 +01:00
|
|
|
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2023-07-05 20:13:26 +01:00
|
|
|
Ty::new_fn_ptr(
|
|
|
|
tcx,
|
2024-05-17 14:17:48 -03:00
|
|
|
self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)),
|
2023-07-05 20:13:26 +01:00
|
|
|
)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
|
2024-03-06 19:18:30 +01:00
|
|
|
self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path);
|
|
|
|
|
2022-04-13 16:38:16 -07:00
|
|
|
let repr = match repr {
|
2022-08-29 03:53:33 +00:00
|
|
|
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
|
|
|
|
TraitObjectSyntax::DynStar => ty::DynStar,
|
2022-04-13 16:38:16 -07:00
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_trait_object_ty(
|
2024-02-11 09:24:35 +01:00
|
|
|
hir_ty.span,
|
|
|
|
hir_ty.hir_id,
|
2023-06-05 17:08:27 +00:00
|
|
|
bounds,
|
|
|
|
lifetime,
|
|
|
|
borrowed,
|
|
|
|
repr,
|
|
|
|
)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?maybe_qself, ?path);
|
2024-03-15 03:21:55 +01:00
|
|
|
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
2024-02-11 09:24:35 +01:00
|
|
|
self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
|
2016-10-27 05:17:42 +03:00
|
|
|
}
|
2023-01-14 06:47:49 +00:00
|
|
|
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
|
2021-01-30 12:06:04 +01:00
|
|
|
let opaque_ty = tcx.hir().item(item_id);
|
2020-05-10 11:57:58 +01:00
|
|
|
|
|
|
|
match opaque_ty.kind {
|
2024-02-02 22:45:25 +00:00
|
|
|
hir::ItemKind::OpaqueTy(&hir::OpaqueTy { .. }) => {
|
2023-03-03 12:34:16 -03:00
|
|
|
let local_def_id = item_id.owner_id.def_id;
|
|
|
|
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
|
|
|
|
// generate the def_id of an associated type for the trait and return as
|
|
|
|
// type a projection.
|
2023-06-24 00:00:08 -03:00
|
|
|
let def_id = if in_trait {
|
2023-03-17 03:45:14 +00:00
|
|
|
tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id()
|
2023-03-03 12:34:16 -03:00
|
|
|
} else {
|
|
|
|
local_def_id.to_def_id()
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_opaque_ty(def_id, lifetimes, in_trait)
|
2022-05-20 15:29:45 -03:00
|
|
|
}
|
2020-05-10 11:57:58 +01:00
|
|
|
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
|
|
|
}
|
2019-02-28 22:43:53 +00:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?qself, ?segment);
|
2024-03-15 03:21:55 +01:00
|
|
|
let ty = self.lower_ty_common(qself, false, true);
|
2024-02-11 09:24:35 +01:00
|
|
|
self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false)
|
2019-12-24 17:38:22 -05:00
|
|
|
.map(|(ty, _, _)| ty)
|
2023-07-05 20:13:26 +01:00
|
|
|
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-11-23 06:01:35 +00:00
|
|
|
&hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
|
2020-08-04 14:34:24 +01:00
|
|
|
let def_id = tcx.require_lang_item(lang_item, Some(span));
|
2024-03-15 03:21:55 +01:00
|
|
|
let (args, _) = self.lower_generic_args_of_path(
|
2020-08-04 14:34:24 +01:00
|
|
|
span,
|
|
|
|
def_id,
|
|
|
|
&[],
|
2021-01-02 19:45:11 +01:00
|
|
|
&hir::PathSegment::invalid(),
|
2020-08-04 14:34:24 +01:00
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2020-08-04 14:34:24 +01:00
|
|
|
);
|
2023-07-11 22:35:29 +01:00
|
|
|
tcx.at(span).type_of(def_id).instantiate(tcx, args)
|
2020-08-04 14:34:24 +01:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Array(ty, length) => {
|
2021-12-23 10:01:51 +01:00
|
|
|
let length = match length {
|
2024-01-27 18:59:20 +03:00
|
|
|
hir::ArrayLen::Infer(inf) => self.ct_infer(tcx.types.usize, None, inf.span),
|
2021-12-23 10:01:51 +01:00
|
|
|
hir::ArrayLen::Body(constant) => {
|
2022-11-06 19:17:57 +00:00
|
|
|
ty::Const::from_anon_const(tcx, constant.def_id)
|
2021-12-23 10:01:51 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
|
2014-01-29 00:05:11 -05:00
|
|
|
}
|
2024-02-01 08:18:55 +00:00
|
|
|
hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(),
|
2018-07-11 22:41:03 +08:00
|
|
|
hir::TyKind::Infer => {
|
2018-08-22 01:35:02 +01:00
|
|
|
// Infer also appears as the type of arguments or return
|
2021-08-22 14:46:15 +02:00
|
|
|
// values in an ExprKind::Closure, or as
|
2016-05-11 08:48:12 +03:00
|
|
|
// the type of local variables. Both of these cases are
|
|
|
|
// handled specially and will not descend into this routine.
|
2024-02-11 09:24:35 +01:00
|
|
|
self.ty_infer(None, hir_ty.span)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-02-02 13:57:36 +00:00
|
|
|
hir::TyKind::Pat(ty, pat) => {
|
|
|
|
let ty = self.lower_ty(ty);
|
|
|
|
let pat_ty = match pat.kind {
|
|
|
|
hir::PatKind::Wild => {
|
|
|
|
let err = tcx.dcx().emit_err(WildPatTy { span: pat.span });
|
|
|
|
Ty::new_error(tcx, err)
|
|
|
|
}
|
|
|
|
hir::PatKind::Range(start, end, include_end) => {
|
|
|
|
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
|
|
|
|
let (expr, neg) = match expr.kind {
|
|
|
|
hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
|
|
|
|
(negated, Some((expr.hir_id, expr.span)))
|
|
|
|
}
|
|
|
|
_ => (expr, None),
|
|
|
|
};
|
|
|
|
let c = match &expr.kind {
|
|
|
|
hir::ExprKind::Lit(lit) => {
|
|
|
|
let lit_input =
|
|
|
|
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
|
|
|
|
match tcx.lit_to_const(lit_input) {
|
|
|
|
Ok(c) => c,
|
|
|
|
Err(LitToConstError::Reported(err)) => {
|
|
|
|
ty::Const::new_error(tcx, err, ty)
|
|
|
|
}
|
|
|
|
Err(LitToConstError::TypeError) => todo!(),
|
|
|
|
}
|
|
|
|
}
|
2024-02-20 12:32:28 -03:00
|
|
|
|
|
|
|
hir::ExprKind::Path(hir::QPath::Resolved(
|
|
|
|
_,
|
2024-05-11 15:40:34 +02:00
|
|
|
path @ &hir::Path {
|
|
|
|
res: Res::Def(DefKind::ConstParam, def_id),
|
|
|
|
..
|
2024-02-20 12:32:28 -03:00
|
|
|
},
|
|
|
|
)) => {
|
2024-05-11 15:40:34 +02:00
|
|
|
let _ = self.prohibit_generic_args(
|
|
|
|
path.segments.iter(),
|
|
|
|
GenericsArgsErrExtend::Param(def_id),
|
|
|
|
);
|
2024-02-20 12:32:28 -03:00
|
|
|
let ty = tcx
|
|
|
|
.type_of(def_id)
|
|
|
|
.no_bound_vars()
|
|
|
|
.expect("const parameter types cannot be generic");
|
2024-04-10 16:26:00 -03:00
|
|
|
self.lower_const_param(expr.hir_id, ty)
|
2024-02-20 12:32:28 -03:00
|
|
|
}
|
|
|
|
|
2023-02-02 13:57:36 +00:00
|
|
|
_ => {
|
|
|
|
let err = tcx
|
|
|
|
.dcx()
|
|
|
|
.emit_err(crate::errors::NonConstRange { span: expr.span });
|
|
|
|
ty::Const::new_error(tcx, err, ty)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
self.record_ty(expr.hir_id, c.ty(), expr.span);
|
|
|
|
if let Some((id, span)) = neg {
|
|
|
|
self.record_ty(id, c.ty(), span);
|
|
|
|
}
|
|
|
|
c
|
|
|
|
};
|
|
|
|
|
|
|
|
let start = start.map(expr_to_const);
|
|
|
|
let end = end.map(expr_to_const);
|
|
|
|
|
|
|
|
let include_end = match include_end {
|
|
|
|
hir::RangeEnd::Included => true,
|
|
|
|
hir::RangeEnd::Excluded => false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
|
|
|
|
Ty::new_pat(tcx, ty, pat)
|
|
|
|
}
|
|
|
|
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
|
2024-04-08 21:02:13 +00:00
|
|
|
_ => Ty::new_error_with_message(
|
|
|
|
tcx,
|
|
|
|
pat.span,
|
|
|
|
format!("unsupported pattern for pattern type: {pat:#?}"),
|
|
|
|
),
|
2023-02-02 13:57:36 +00:00
|
|
|
};
|
|
|
|
self.record_ty(pat.hir_id, ty, pat.span);
|
|
|
|
pat_ty
|
|
|
|
}
|
2023-07-05 20:13:26 +01:00
|
|
|
hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
|
2016-05-12 14:19:26 -04:00
|
|
|
};
|
|
|
|
|
2024-02-11 09:24:35 +01:00
|
|
|
self.record_ty(hir_ty.hir_id, result_ty, hir_ty.span);
|
2016-05-12 14:19:26 -04:00
|
|
|
result_ty
|
2016-05-02 18:07:04 +03:00
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
|
2024-02-11 09:24:35 +01:00
|
|
|
#[instrument(level = "debug", skip_all, ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
fn lower_opaque_ty(
|
2019-12-01 16:08:58 +01:00
|
|
|
&self,
|
|
|
|
def_id: DefId,
|
|
|
|
lifetimes: &[hir::GenericArg<'_>],
|
2022-09-06 17:37:00 +02:00
|
|
|
in_trait: bool,
|
2019-12-01 16:08:58 +01:00
|
|
|
) -> Ty<'tcx> {
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?def_id, ?lifetimes);
|
2017-10-15 13:43:06 -07:00
|
|
|
let tcx = self.tcx();
|
2018-05-22 14:31:56 +02:00
|
|
|
|
2017-10-15 13:43:06 -07:00
|
|
|
let generics = tcx.generics_of(def_id);
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?generics);
|
2017-10-15 13:43:06 -07:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
2023-03-17 12:37:27 -03:00
|
|
|
// We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
|
|
|
|
// since return-position impl trait in trait squashes all of the generics from its source fn
|
|
|
|
// into its own generics, so the opaque's "own" params isn't always just lifetimes.
|
|
|
|
if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
|
|
|
|
{
|
|
|
|
// Resolve our own lifetime parameters.
|
2023-12-15 03:19:46 +00:00
|
|
|
let GenericParamDefKind::Lifetime { .. } = param.kind else {
|
|
|
|
span_bug!(
|
|
|
|
tcx.def_span(param.def_id),
|
|
|
|
"only expected lifetime for opaque's own generics, got {:?}",
|
|
|
|
param.kind
|
|
|
|
);
|
|
|
|
};
|
|
|
|
let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
|
|
|
|
bug!(
|
|
|
|
"expected lifetime argument for param {param:?}, found {:?}",
|
|
|
|
&lifetimes[i]
|
|
|
|
)
|
|
|
|
};
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_lifetime(lifetime, None).into()
|
2018-05-16 11:56:50 +03:00
|
|
|
} else {
|
2022-10-23 20:38:34 +00:00
|
|
|
tcx.mk_param_from_def(param)
|
2017-10-15 13:43:06 -07:00
|
|
|
}
|
2018-05-16 11:56:50 +03:00
|
|
|
});
|
2024-02-11 09:24:35 +01:00
|
|
|
debug!(?args);
|
2017-10-15 13:43:06 -07:00
|
|
|
|
2023-07-05 20:13:26 +01:00
|
|
|
if in_trait {
|
2023-07-11 22:35:29 +01:00
|
|
|
Ty::new_projection(tcx, def_id, args)
|
2023-07-05 20:13:26 +01:00
|
|
|
} else {
|
2023-07-11 22:35:29 +01:00
|
|
|
Ty::new_opaque(tcx, def_id, args)
|
2023-07-05 20:13:26 +01:00
|
|
|
}
|
2017-10-15 13:43:06 -07:00
|
|
|
}
|
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
2019-09-26 17:25:31 +01:00
|
|
|
match ty.kind {
|
2024-03-15 02:19:29 +01:00
|
|
|
hir::TyKind::Infer if let Some(expected_ty) = expected_ty => {
|
|
|
|
self.record_ty(ty.hir_id, expected_ty, ty.span);
|
|
|
|
expected_ty
|
2017-09-16 02:33:41 +03:00
|
|
|
}
|
2024-03-15 03:21:55 +01:00
|
|
|
_ => self.lower_ty(ty),
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2013-04-24 01:29:46 -07:00
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2024-02-11 09:22:52 +01:00
|
|
|
/// Lower a function type from the HIR to our internal notion of a function signature.
|
2024-05-17 14:17:48 -03:00
|
|
|
#[instrument(level = "debug", skip(self, hir_id, safety, abi, decl, generics, hir_ty), ret)]
|
2024-03-15 03:21:55 +01:00
|
|
|
pub fn lower_fn_ty(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2024-03-06 17:24:13 +11:00
|
|
|
hir_id: HirId,
|
2024-05-17 14:17:48 -03:00
|
|
|
safety: hir::Safety,
|
2019-12-24 17:38:22 -05:00
|
|
|
abi: abi::Abi,
|
2023-02-01 14:23:51 +00:00
|
|
|
decl: &hir::FnDecl<'tcx>,
|
2022-02-07 22:58:30 +01:00
|
|
|
generics: Option<&hir::Generics<'_>>,
|
2021-02-10 15:49:23 +00:00
|
|
|
hir_ty: Option<&hir::Ty<'_>>,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
2017-07-29 17:19:57 +03:00
|
|
|
let tcx = self.tcx();
|
2024-03-22 16:27:26 +03:00
|
|
|
let bound_vars = tcx.late_bound_vars(hir_id);
|
2020-10-26 14:18:31 -04:00
|
|
|
debug!(?bound_vars);
|
2014-01-27 14:18:36 +02:00
|
|
|
|
2020-03-06 12:13:55 +01:00
|
|
|
// We proactively collect all the inferred type params to emit a single error per fn def.
|
2022-01-05 11:43:21 +01:00
|
|
|
let mut visitor = HirPlaceholderCollector::default();
|
2022-03-27 19:43:05 -07:00
|
|
|
let mut infer_replacements = vec![];
|
|
|
|
|
2022-02-07 22:58:30 +01:00
|
|
|
if let Some(generics) = generics {
|
|
|
|
walk_generics(&mut visitor, generics);
|
|
|
|
}
|
2020-03-22 18:50:30 -07:00
|
|
|
|
2022-03-27 19:43:05 -07:00
|
|
|
let input_tys: Vec<_> = decl
|
|
|
|
.inputs
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, a)| {
|
|
|
|
if let hir::TyKind::Infer = a.kind
|
2024-03-15 03:21:55 +01:00
|
|
|
&& !self.allow_infer()
|
2022-03-27 19:43:05 -07:00
|
|
|
{
|
|
|
|
if let Some(suggested_ty) =
|
2022-03-27 19:43:08 -07:00
|
|
|
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
|
|
|
|
{
|
2022-03-27 19:43:05 -07:00
|
|
|
infer_replacements.push((a.span, suggested_ty.to_string()));
|
2024-01-12 16:33:13 +00:00
|
|
|
return Ty::new_error_with_message(
|
|
|
|
self.tcx(),
|
|
|
|
a.span,
|
|
|
|
suggested_ty.to_string(),
|
|
|
|
);
|
2022-03-27 19:43:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only visit the type looking for `_` if we didn't fix the type above
|
|
|
|
visitor.visit_ty(a);
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_arg_ty(a, None)
|
2022-03-27 19:43:05 -07:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
let output_ty = match decl.output {
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::FnRetTy::Return(output) => {
|
2022-03-27 19:43:08 -07:00
|
|
|
if let hir::TyKind::Infer = output.kind
|
2024-03-15 03:21:55 +01:00
|
|
|
&& !self.allow_infer()
|
2022-03-27 19:43:08 -07:00
|
|
|
&& let Some(suggested_ty) =
|
|
|
|
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
|
|
|
|
{
|
|
|
|
infer_replacements.push((output.span, suggested_ty.to_string()));
|
2024-01-12 16:33:13 +00:00
|
|
|
Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string())
|
2022-03-27 19:43:08 -07:00
|
|
|
} else {
|
|
|
|
visitor.visit_ty(output);
|
2024-03-15 03:21:55 +01:00
|
|
|
self.lower_ty(output)
|
2022-03-27 19:43:08 -07:00
|
|
|
}
|
2019-12-23 14:16:34 -08:00
|
|
|
}
|
2024-05-02 17:49:23 +02:00
|
|
|
hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
|
2016-05-11 08:48:12 +03:00
|
|
|
};
|
2014-01-27 14:18:36 +02:00
|
|
|
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?output_ty);
|
2016-08-31 16:40:43 +12:00
|
|
|
|
2024-05-17 14:17:48 -03:00
|
|
|
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
|
2020-10-26 14:18:31 -04:00
|
|
|
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
|
2017-07-29 17:19:57 +03:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
if !self.allow_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
|
2019-12-30 11:45:48 -08:00
|
|
|
// We always collect the spans for placeholder types when evaluating `fn`s, but we
|
|
|
|
// only want to emit an error complaining about them if infer types (`_`) are not
|
2024-02-11 09:22:52 +01:00
|
|
|
// allowed. `allow_infer` gates this behavior. We check for the presence of
|
2020-03-24 11:35:48 -07:00
|
|
|
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2022-03-27 19:43:05 -07:00
|
|
|
let mut diag = crate::collect::placeholder_type_error_diag(
|
2019-12-27 04:15:48 -08:00
|
|
|
tcx,
|
2022-02-07 22:58:30 +01:00
|
|
|
generics,
|
2019-12-27 04:15:48 -08:00
|
|
|
visitor.0,
|
2022-03-27 19:43:05 -07:00
|
|
|
infer_replacements.iter().map(|(s, _)| *s).collect(),
|
2020-03-24 11:35:48 -07:00
|
|
|
true,
|
2021-02-10 15:49:23 +00:00
|
|
|
hir_ty,
|
2021-06-19 07:01:37 +08:00
|
|
|
"function",
|
2019-12-27 04:15:48 -08:00
|
|
|
);
|
2022-03-27 19:43:05 -07:00
|
|
|
|
|
|
|
if !infer_replacements.is_empty() {
|
2022-05-24 13:00:36 +02:00
|
|
|
diag.multipart_suggestion(
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
format!(
|
2022-03-27 19:43:05 -07:00
|
|
|
"try replacing `_` with the type{} in the corresponding trait method signature",
|
2022-03-27 19:43:08 -07:00
|
|
|
rustc_errors::pluralize!(infer_replacements.len()),
|
2022-05-24 13:00:36 +02:00
|
|
|
),
|
|
|
|
infer_replacements,
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
2022-03-27 19:43:05 -07:00
|
|
|
}
|
|
|
|
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(diag.emit());
|
2019-12-27 04:15:48 -08:00
|
|
|
}
|
2019-12-23 14:16:34 -08:00
|
|
|
|
2017-07-29 17:19:57 +03:00
|
|
|
// Find any late-bound regions declared in return type that do
|
2018-09-26 17:32:23 +02:00
|
|
|
// not appear in the arguments. These are not well-formed.
|
2017-07-29 17:19:57 +03:00
|
|
|
//
|
|
|
|
// Example:
|
|
|
|
// for<'a> fn() -> &'a str <-- 'a is bad
|
|
|
|
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok
|
|
|
|
let inputs = bare_fn_ty.inputs();
|
2019-12-24 17:38:22 -05:00
|
|
|
let late_bound_in_args =
|
2024-02-20 13:50:39 +01:00
|
|
|
tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
|
2017-07-29 17:19:57 +03:00
|
|
|
let output = bare_fn_ty.output();
|
2024-02-20 13:50:39 +01:00
|
|
|
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
|
2020-07-25 02:03:50 -07:00
|
|
|
|
|
|
|
self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
|
2024-01-04 09:08:36 +11:00
|
|
|
struct_span_code_err!(
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx(),
|
2019-12-24 17:38:22 -05:00
|
|
|
decl.output.span(),
|
|
|
|
E0581,
|
2020-07-25 02:47:16 -07:00
|
|
|
"return type references {}, which is not constrained by the fn input types",
|
2020-07-25 02:03:50 -07:00
|
|
|
br_name
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
|
|
|
bare_fn_ty
|
|
|
|
}
|
|
|
|
|
2022-03-27 19:43:05 -07:00
|
|
|
/// Given a fn_hir_id for a impl function, suggest the type that is found on the
|
|
|
|
/// corresponding function in the trait that the impl implements, if it exists.
|
2022-03-27 19:43:08 -07:00
|
|
|
/// If arg_idx is Some, then it corresponds to an input type index, otherwise it
|
|
|
|
/// corresponds to the return type.
|
2022-03-27 19:43:05 -07:00
|
|
|
fn suggest_trait_fn_ty_for_impl_fn_infer(
|
|
|
|
&self,
|
2024-03-06 17:24:13 +11:00
|
|
|
fn_hir_id: HirId,
|
2022-03-27 19:43:08 -07:00
|
|
|
arg_idx: Option<usize>,
|
2022-03-27 19:43:05 -07:00
|
|
|
) -> Option<Ty<'tcx>> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
|
2023-12-01 05:28:34 -08:00
|
|
|
tcx.hir_node(fn_hir_id)
|
2022-03-27 19:43:05 -07:00
|
|
|
else {
|
|
|
|
return None;
|
|
|
|
};
|
2024-02-09 23:58:36 +03:00
|
|
|
let i = tcx.parent_hir_node(fn_hir_id).expect_item().expect_impl();
|
2022-03-27 19:43:05 -07:00
|
|
|
|
2024-03-15 03:21:55 +01:00
|
|
|
let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty));
|
2022-03-27 19:43:05 -07:00
|
|
|
|
2022-04-24 23:32:59 -07:00
|
|
|
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
|
2022-03-27 19:43:05 -07:00
|
|
|
tcx,
|
|
|
|
*ident,
|
|
|
|
ty::AssocKind::Fn,
|
|
|
|
trait_ref.def_id,
|
|
|
|
)?;
|
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(
|
2022-03-27 19:43:05 -07:00
|
|
|
tcx,
|
2023-07-11 22:35:29 +01:00
|
|
|
trait_ref.args.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
|
2022-03-27 19:43:05 -07:00
|
|
|
);
|
2023-03-16 04:02:56 +00:00
|
|
|
let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
|
2022-03-27 19:43:05 -07:00
|
|
|
|
2023-03-16 04:02:56 +00:00
|
|
|
Some(if let Some(arg_idx) = arg_idx {
|
|
|
|
*fn_sig.inputs().get(arg_idx)?
|
|
|
|
} else {
|
|
|
|
fn_sig.output()
|
|
|
|
})
|
2022-03-27 19:43:05 -07:00
|
|
|
}
|
|
|
|
|
2022-10-23 20:38:34 +00:00
|
|
|
#[instrument(level = "trace", skip(self, generate_err))]
|
2020-07-25 02:03:50 -07:00
|
|
|
fn validate_late_bound_regions(
|
|
|
|
&self,
|
2020-12-18 13:24:55 -05:00
|
|
|
constrained_regions: FxHashSet<ty::BoundRegionKind>,
|
|
|
|
referenced_regions: FxHashSet<ty::BoundRegionKind>,
|
2024-02-23 10:20:45 +11:00
|
|
|
generate_err: impl Fn(&str) -> Diag<'tcx>,
|
2020-07-25 02:03:50 -07:00
|
|
|
) {
|
|
|
|
for br in referenced_regions.difference(&constrained_regions) {
|
|
|
|
let br_name = match *br {
|
2023-08-03 15:56:56 +00:00
|
|
|
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon | ty::BrEnv => {
|
2022-05-11 22:49:39 +02:00
|
|
|
"an anonymous lifetime".to_string()
|
|
|
|
}
|
2023-07-25 23:17:39 +02:00
|
|
|
ty::BrNamed(_, name) => format!("lifetime `{name}`"),
|
2020-07-25 02:03:50 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut err = generate_err(&br_name);
|
|
|
|
|
2023-08-03 15:56:56 +00:00
|
|
|
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon = *br {
|
2018-01-22 17:36:43 -05:00
|
|
|
// The only way for an anonymous lifetime to wind up
|
|
|
|
// in the return type but **also** be unconstrained is
|
|
|
|
// if it only appears in "associated types" in the
|
2020-07-25 02:03:50 -07:00
|
|
|
// input. See #47511 and #62200 for examples. In this case,
|
2018-01-22 17:36:43 -05:00
|
|
|
// though we can easily give a hint that ought to be
|
|
|
|
// relevant.
|
2019-12-24 17:38:22 -05:00
|
|
|
err.note(
|
2022-08-25 10:30:46 +00:00
|
|
|
"lifetimes appearing in an associated or opaque type are not considered constrained",
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2022-08-25 10:30:46 +00:00
|
|
|
err.note("consider introducing a named lifetime parameter");
|
2018-01-22 17:36:43 -05:00
|
|
|
}
|
2020-07-25 02:03:50 -07:00
|
|
|
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(err.emit());
|
2017-07-29 17:19:57 +03:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2014-05-06 16:37:32 -07:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
/// Given the bounds on an object, determines what single region bound (if any) we can
|
2024-02-11 09:22:52 +01:00
|
|
|
/// use to summarize this type.
|
|
|
|
///
|
|
|
|
/// The basic idea is that we will use the bound the user
|
2016-05-11 08:48:12 +03:00
|
|
|
/// provided, if they provided one, and otherwise search the supertypes of trait bounds
|
|
|
|
/// for region bounds. It may be that we can derive no bound at all, in which case
|
|
|
|
/// we return `None`.
|
2023-11-12 11:59:01 +01:00
|
|
|
#[instrument(level = "debug", skip(self, span), ret)]
|
2019-12-24 17:38:22 -05:00
|
|
|
fn compute_object_lifetime_bound(
|
|
|
|
&self,
|
2016-05-11 08:48:12 +03:00
|
|
|
span: Span,
|
2022-11-19 03:28:56 +00:00
|
|
|
existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> Option<ty::Region<'tcx>> // if None, use the default
|
2016-05-11 08:48:12 +03:00
|
|
|
{
|
|
|
|
let tcx = self.tcx();
|
2015-02-11 19:16:47 -05:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
// No explicit region bound specified. Therefore, examine trait
|
|
|
|
// bounds and see if we can derive region bounds from those.
|
2019-12-24 17:38:22 -05:00
|
|
|
let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
// If there are no derived region bounds, then report back that we
|
|
|
|
// can find no region bound. The caller will use the default.
|
|
|
|
if derived_region_bounds.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
// If any of the derived region bounds are 'static, that is always
|
|
|
|
// the best choice.
|
2022-01-28 11:25:15 +11:00
|
|
|
if derived_region_bounds.iter().any(|r| r.is_static()) {
|
2019-04-25 22:05:04 +01:00
|
|
|
return Some(tcx.lifetimes.re_static);
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
// Determine whether there is exactly one unique region in the set
|
|
|
|
// of derived region bounds. If so, use that. Otherwise, report an
|
|
|
|
// error.
|
|
|
|
let r = derived_region_bounds[0];
|
|
|
|
if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
|
2024-01-10 14:58:03 +00:00
|
|
|
self.set_tainted_by_errors(tcx.dcx().emit_err(AmbiguousLifetimeBound { span }));
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2020-03-20 15:03:11 +01:00
|
|
|
Some(r)
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
2016-05-02 18:07:47 +03:00
|
|
|
}
|
2023-11-24 09:53:10 +01:00
|
|
|
|
|
|
|
fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
|
|
|
|
match kind {
|
|
|
|
ty::AssocKind::Fn => "function",
|
|
|
|
ty::AssocKind::Const => "constant",
|
|
|
|
ty::AssocKind::Type => "type",
|
|
|
|
}
|
|
|
|
}
|