2018-11-27 02:59:49 +00:00
|
|
|
//! Conversion from AST representation of types to the `ty.rs` representation.
|
2019-01-04 17:50:53 +00:00
|
|
|
//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
|
|
|
|
//! instance of `AstConv`.
|
2014-11-26 04:52:02 -05:00
|
|
|
|
2020-08-19 19:07:03 +02:00
|
|
|
mod errors;
|
2023-01-11 19:07:03 +00:00
|
|
|
pub mod generics;
|
2020-01-13 20:30:35 -08:00
|
|
|
|
2023-01-11 19:07:03 +00:00
|
|
|
use crate::astconv::generics::{
|
|
|
|
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
|
|
|
|
};
|
2020-08-19 19:07:03 +02:00
|
|
|
use crate::bounds::Bounds;
|
2022-01-05 11:43:21 +01:00
|
|
|
use crate::collect::HirPlaceholderCollector;
|
2020-08-27 20:09:22 +10:00
|
|
|
use crate::errors::{
|
|
|
|
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
|
|
|
|
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
|
|
|
|
};
|
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;
|
2019-12-24 05:02:53 +01:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
2022-01-23 12:34:26 -06:00
|
|
|
use rustc_errors::{
|
2022-08-10 03:39:41 +00:00
|
|
|
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
|
|
|
|
MultiSpan,
|
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 _};
|
2022-05-20 15:29:45 -03:00
|
|
|
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
|
2022-12-08 13:31:21 +01:00
|
|
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
|
|
|
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
|
|
|
use rustc_infer::traits::ObligationCause;
|
|
|
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
2022-06-04 17:05:33 -05:00
|
|
|
use rustc_middle::middle::stability::AllowUnstable;
|
2022-09-16 15:31:10 +02:00
|
|
|
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
|
2023-02-06 17:48:12 -07:00
|
|
|
use rustc_middle::ty::DynKind;
|
2020-08-19 19:07:03 +02:00
|
|
|
use rustc_middle::ty::GenericParamDefKind;
|
2022-10-26 21:50:25 +00:00
|
|
|
use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitable};
|
2021-07-10 10:00:54 +02:00
|
|
|
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
|
|
|
|
use rustc_span::edition::Edition;
|
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
|
|
|
use rustc_span::lev_distance::find_best_match_for_name;
|
2022-05-27 19:53:31 -07:00
|
|
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
2023-01-22 05:11:24 +00: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;
|
2022-06-22 23:06:34 +01:00
|
|
|
use rustc_trait_selection::traits::error_reporting::{
|
|
|
|
report_object_safety_error, suggestions::NextTypeParamName,
|
|
|
|
};
|
2022-12-08 13:31:21 +01:00
|
|
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
2020-02-11 21:19:40 +01:00
|
|
|
use rustc_trait_selection::traits::wf::object_region_bounds;
|
2022-12-08 13:31:21 +01:00
|
|
|
use rustc_trait_selection::traits::{astconv_object_safety_violations, NormalizeExt};
|
2018-11-27 02:59:49 +00:00
|
|
|
|
2022-08-07 22:02:02 +02:00
|
|
|
use smallvec::{smallvec, SmallVec};
|
2018-11-27 02:59:49 +00:00
|
|
|
use std::collections::BTreeSet;
|
|
|
|
use std::slice;
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2018-12-18 18:59:00 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct PathSeg(pub DefId, pub usize);
|
2018-12-03 21:50:49 +00:00
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub trait AstConv<'tcx> {
|
2023-01-22 05:11:24 +00:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx>;
|
2015-01-04 06:10:34 -05:00
|
|
|
|
2022-10-31 16:19:36 +00:00
|
|
|
fn item_def_id(&self) -> DefId;
|
2019-11-01 13:50:36 +01:00
|
|
|
|
2020-12-03 20:10:55 -03:00
|
|
|
/// Returns predicates in scope of the form `X: Foo<T>`, where `X`
|
|
|
|
/// is a type parameter `X` with the given id `def_id` and T
|
|
|
|
/// matches `assoc_name`. This is a subset of the full set of
|
|
|
|
/// predicates.
|
2019-07-12 06:29:27 -04:00
|
|
|
///
|
|
|
|
/// This is used for one specific purpose: resolving "short-hand"
|
|
|
|
/// associated type references like `T::Item`. 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".
|
2020-12-03 20:10:55 -03:00
|
|
|
fn get_type_parameter_bounds(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
def_id: DefId,
|
|
|
|
assoc_name: Ident,
|
|
|
|
) -> ty::GenericPredicates<'tcx>;
|
2015-02-17 11:04:25 -05:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// Returns the lifetime to use when a lifetime is omitted (and not elided).
|
2019-12-24 17:38:22 -05:00
|
|
|
fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
|
|
|
|
-> Option<ty::Region<'tcx>>;
|
2017-01-13 15:09:56 +02:00
|
|
|
|
2019-02-28 22:43:53 +00:00
|
|
|
/// Returns the type to use when a type is omitted.
|
2019-06-06 01:55:34 +01:00
|
|
|
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
|
2016-08-17 03:56:18 +03:00
|
|
|
|
2019-12-30 11:45:48 -08:00
|
|
|
/// Returns `true` if `_` is allowed in type signatures in the current context.
|
2019-12-23 14:16:34 -08:00
|
|
|
fn allow_ty_infer(&self) -> bool;
|
|
|
|
|
2019-06-06 01:55:34 +01:00
|
|
|
/// Returns the const to use when a const is omitted.
|
2019-06-06 01:55:09 +01:00
|
|
|
fn ct_infer(
|
|
|
|
&self,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
param: Option<&ty::GenericParamDef>,
|
|
|
|
span: Span,
|
2022-02-02 14:24:45 +11:00
|
|
|
) -> Const<'tcx>;
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
/// Projecting an associated type from a (potentially)
|
|
|
|
/// higher-ranked trait reference is more complicated, because of
|
|
|
|
/// the possibility of late-bound regions appearing in the
|
|
|
|
/// associated type binding. This is not legal in function
|
|
|
|
/// signatures for that reason. In a function body, we can always
|
|
|
|
/// handle it because we can use inference variables to remove the
|
|
|
|
/// late-bound regions.
|
2019-12-24 17:38:22 -05:00
|
|
|
fn projected_ty_from_poly_trait_ref(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
item_def_id: DefId,
|
2019-12-01 16:08:58 +01:00
|
|
|
item_segment: &hir::PathSegment<'_>,
|
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.
|
|
|
|
/// Note that `ty` might be a projection type that needs normalization.
|
|
|
|
/// 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
|
|
|
|
|
|
|
/// Invoked when we encounter an error from some prior pass
|
2018-11-27 02:59:49 +00:00
|
|
|
/// (e.g., resolve) that is translated into a ty-error. This is
|
2016-03-15 04:49:10 -04:00
|
|
|
/// 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
|
|
|
|
|
|
|
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
|
2023-01-11 18:58:44 +00:00
|
|
|
|
|
|
|
fn astconv(&self) -> &dyn AstConv<'tcx>
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
self
|
|
|
|
}
|
2023-01-22 05:11:24 +00:00
|
|
|
|
|
|
|
fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
|
2012-05-15 08:29:22 -07:00
|
|
|
}
|
|
|
|
|
2020-11-30 09:26:22 +01:00
|
|
|
#[derive(Debug)]
|
2019-06-12 11:43:15 +03:00
|
|
|
struct ConvertedBinding<'a, 'tcx> {
|
2021-02-18 21:01:44 +01:00
|
|
|
hir_id: hir::HirId,
|
2020-04-19 13:00:18 +02:00
|
|
|
item_name: Ident,
|
2019-06-12 11:43:15 +03:00
|
|
|
kind: ConvertedBindingKind<'a, 'tcx>,
|
2020-11-30 09:26:22 +01:00
|
|
|
gen_args: &'a GenericArgs<'a>,
|
2016-05-02 18:07:47 +03:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2020-11-30 09:26:22 +01:00
|
|
|
#[derive(Debug)]
|
2019-06-12 11:43:15 +03:00
|
|
|
enum ConvertedBindingKind<'a, 'tcx> {
|
2022-01-10 23:39:21 +00:00
|
|
|
Equality(ty::Term<'tcx>),
|
2019-12-01 16:08:58 +01:00
|
|
|
Constraint(&'a [hir::GenericBound<'a>]),
|
2019-03-16 00:04:02 +00: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.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[derive(Clone, Default, Debug)]
|
2020-02-22 01:55:35 +00:00
|
|
|
pub struct GenericArgCountMismatch {
|
|
|
|
/// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
|
2022-01-23 12:34:26 -06:00
|
|
|
pub reported: Option<ErrorGuaranteed>,
|
2020-02-22 01:55:35 +00:00
|
|
|
/// A list of spans of arguments provided that were not valid.
|
|
|
|
pub invalid_args: Vec<Span>,
|
|
|
|
}
|
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>,
|
|
|
|
}
|
|
|
|
|
2020-11-13 15:49:17 +01:00
|
|
|
pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
|
|
|
|
fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'a>>, bool);
|
|
|
|
|
|
|
|
fn provided_kind(
|
|
|
|
&mut self,
|
|
|
|
param: &ty::GenericParamDef,
|
|
|
|
arg: &GenericArg<'_>,
|
|
|
|
) -> subst::GenericArg<'tcx>;
|
|
|
|
|
|
|
|
fn inferred_kind(
|
|
|
|
&mut self,
|
|
|
|
substs: Option<&[subst::GenericArg<'tcx>]>,
|
|
|
|
param: &ty::GenericParamDef,
|
|
|
|
infer_args: bool,
|
|
|
|
) -> subst::GenericArg<'tcx>;
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn ast_region_to_region(
|
|
|
|
&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();
|
2020-08-12 12:22:56 +02:00
|
|
|
let lifetime_name = |def_id| tcx.hir().name(tcx.hir().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-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_late_bound(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];
|
2023-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, 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-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_free(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-02-18 03:28:43 +00:00
|
|
|
Some(rbv::ResolvedArg::Error(_)) => {
|
|
|
|
bug!("only ty/ct should resolve as ResolvedArg::Error")
|
|
|
|
}
|
|
|
|
|
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-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_error_with_message(
|
|
|
|
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
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
|
|
|
|
/// returns an appropriate set of substitutions for this particular reference to `I`.
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn ast_path_substs_for_ty(
|
|
|
|
&self,
|
2016-05-11 08:48:12 +03:00
|
|
|
span: Span,
|
2016-08-08 23:39:49 +03:00
|
|
|
def_id: DefId,
|
2019-12-01 16:08:58 +01:00
|
|
|
item_segment: &hir::PathSegment<'_>,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> SubstsRef<'tcx> {
|
2020-10-26 14:18:31 -04:00
|
|
|
let (substs, _) = self.create_substs_for_ast_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,
|
|
|
|
item_segment.args(),
|
2019-06-12 11:42:58 +03:00
|
|
|
item_segment.infer_args,
|
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2019-06-12 11:42:58 +03:00
|
|
|
);
|
2022-09-29 22:44:24 +00:00
|
|
|
if let Some(b) = item_segment.args().bindings.first() {
|
2023-01-11 19:07:03 +00:00
|
|
|
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
2020-04-24 13:58:41 -07:00
|
|
|
}
|
2015-02-12 05:05:09 -05:00
|
|
|
|
2016-08-17 04:05:00 +03:00
|
|
|
substs
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2012-05-15 08:29:22 -07:00
|
|
|
|
2019-05-03 14:42:04 +01:00
|
|
|
/// Given the type/lifetime/const arguments provided to some path (along with
|
2019-02-28 22:43:53 +00:00
|
|
|
/// an implicit `Self`, if this is a trait reference), returns the complete
|
2016-08-17 04:05:00 +03:00
|
|
|
/// set of substitutions. This may involve applying defaulted type parameters.
|
2022-03-30 15:14:15 -04:00
|
|
|
/// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`.
|
2016-08-17 04:05:00 +03:00
|
|
|
///
|
2019-06-05 21:08:36 +01:00
|
|
|
/// Example:
|
|
|
|
///
|
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
|
|
|
|
/// parameters are returned in the `SubstsRef`, the associated type bindings like
|
2021-12-19 22:01:48 -05:00
|
|
|
/// `Output = u32` are returned from `create_assoc_bindings_for_generic_args`.
|
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>
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// We have the parent substs are the substs for the parent trait:
|
|
|
|
/// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
|
|
|
|
/// type itself: `['a]`. The returned `SubstsRef` concatenates these two
|
|
|
|
/// lists: `[Vec<u8>, u8, 'a]`.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self, span), ret)]
|
2019-12-24 17:38:22 -05:00
|
|
|
fn create_substs_for_ast_path<'a>(
|
|
|
|
&self,
|
2016-05-11 08:48:12 +03:00
|
|
|
span: Span,
|
2016-08-08 23:39:49 +03:00
|
|
|
def_id: DefId,
|
2019-12-08 17:04:17 +00:00
|
|
|
parent_substs: &[subst::GenericArg<'tcx>],
|
2021-01-02 19:45:11 +01:00
|
|
|
seg: &hir::PathSegment<'_>,
|
2019-12-01 16:08:58 +01:00
|
|
|
generic_args: &'a hir::GenericArgs<'_>,
|
2019-06-07 10:18:03 +01:00
|
|
|
infer_args: bool,
|
2019-12-24 17:38:22 -05:00
|
|
|
self_ty: Option<Ty<'tcx>>,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness: ty::BoundConstness,
|
2020-10-26 14:18:31 -04:00
|
|
|
) -> (SubstsRef<'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);
|
2020-11-30 09:26:22 +01:00
|
|
|
debug!("generics: {:?}", 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() {
|
2019-12-08 17:04:17 +00:00
|
|
|
// The parent is a trait so it should have at least one subst
|
|
|
|
// for the `Self` type.
|
|
|
|
assert!(!parent_substs.is_empty())
|
|
|
|
} 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-01-11 19:07:03 +00:00
|
|
|
let arg_count = check_generic_arg_count(
|
2018-12-26 00:07:31 +00:00
|
|
|
tcx,
|
2018-08-08 00:01:47 +01:00
|
|
|
span,
|
2021-01-02 19:45:11 +01:00
|
|
|
def_id,
|
|
|
|
seg,
|
2021-09-30 19:38:50 +02:00
|
|
|
generics,
|
|
|
|
generic_args,
|
2018-08-20 12:52:56 +01:00
|
|
|
GenericArgPosition::Type,
|
2019-12-08 17:04:17 +00:00
|
|
|
self_ty.is_some(),
|
2019-06-07 10:18:03 +01:00
|
|
|
infer_args,
|
2018-08-08 00:01:47 +01:00
|
|
|
);
|
2012-05-15 08:29:22 -07: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
|
|
|
|
// here and so associated type bindings will be handled regardless of whether there are any
|
|
|
|
// non-`Self` generic parameters.
|
2021-09-30 19:38:50 +02:00
|
|
|
if generics.params.is_empty() {
|
2022-08-22 04:15:05 +00:00
|
|
|
return (tcx.intern_substs(parent_substs), arg_count);
|
2020-10-21 18:25:28 +02:00
|
|
|
}
|
|
|
|
|
2020-11-13 15:49:17 +01:00
|
|
|
struct SubstsForAstPathCtxt<'a, 'tcx> {
|
|
|
|
astconv: &'a (dyn AstConv<'tcx> + 'a),
|
|
|
|
def_id: DefId,
|
|
|
|
generic_args: &'a GenericArgs<'a>,
|
|
|
|
span: Span,
|
|
|
|
inferred_params: Vec<Span>,
|
|
|
|
infer_args: bool,
|
|
|
|
}
|
2016-08-17 04:05:00 +03:00
|
|
|
|
2020-11-13 15:49:17 +01:00
|
|
|
impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
|
|
|
|
fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'a>>, bool) {
|
|
|
|
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,
|
|
|
|
arg: &GenericArg<'_>,
|
|
|
|
) -> subst::GenericArg<'tcx> {
|
|
|
|
let tcx = self.astconv.tcx();
|
2021-12-13 03:16:00 +00:00
|
|
|
|
|
|
|
let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
|
|
|
|
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
|
|
|
}
|
|
|
|
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
|
|
|
|
self.inferred_params.push(ty.span);
|
|
|
|
tcx.ty_error().into()
|
|
|
|
} else {
|
|
|
|
self.astconv.ast_ty_to_ty(ty).into()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-11-13 15:49:17 +01:00
|
|
|
match (¶m.kind, arg) {
|
|
|
|
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
2021-09-30 19:38:50 +02:00
|
|
|
self.astconv.ast_region_to_region(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)) => {
|
2020-11-13 15:49:17 +01:00
|
|
|
ty::Const::from_opt_const_arg_anon_const(
|
|
|
|
tcx,
|
|
|
|
ty::WithOptConstParam {
|
2022-11-06 19:17:57 +00:00
|
|
|
did: ct.value.def_id,
|
2020-11-13 15:49:17 +01:00
|
|
|
const_param_did: Some(param.def_id),
|
2020-07-08 15:32:11 -04:00
|
|
|
},
|
2020-05-17 23:00:19 -04:00
|
|
|
)
|
2020-11-13 15:49:17 +01:00
|
|
|
.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");
|
2021-04-24 21:41:57 +00:00
|
|
|
if self.astconv.allow_ty_infer() {
|
2021-12-13 03:16:00 +00:00
|
|
|
self.astconv.ct_infer(ty, Some(param), inf.span).into()
|
2021-04-24 21:41:57 +00:00
|
|
|
} else {
|
|
|
|
self.inferred_params.push(inf.span);
|
2021-12-13 03:16:00 +00:00
|
|
|
tcx.const_error(ty).into()
|
2021-04-24 21:41:57 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-13 15:49:17 +01:00
|
|
|
_ => unreachable!(),
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2020-11-13 15:49:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn inferred_kind(
|
|
|
|
&mut self,
|
|
|
|
substs: Option<&[subst::GenericArg<'tcx>]>,
|
|
|
|
param: &ty::GenericParamDef,
|
|
|
|
infer_args: bool,
|
|
|
|
) -> subst::GenericArg<'tcx> {
|
|
|
|
let tcx = self.astconv.tcx();
|
2018-07-24 02:59:22 +01:00
|
|
|
match param.kind {
|
2022-01-14 18:43:55 -08:00
|
|
|
GenericParamDefKind::Lifetime => self
|
|
|
|
.astconv
|
|
|
|
.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-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_error_with_message(
|
|
|
|
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.
|
2022-08-07 21:03:28 +02:00
|
|
|
let substs = substs.unwrap();
|
|
|
|
if substs.iter().any(|arg| match arg.unpack() {
|
|
|
|
GenericArgKind::Type(ty) => ty.references_error(),
|
|
|
|
_ => false,
|
|
|
|
}) {
|
|
|
|
// Avoid ICE #86756 when type error recovery goes awry.
|
|
|
|
return tcx.ty_error().into();
|
2018-07-24 17:47:31 +01:00
|
|
|
}
|
2023-02-07 01:29:48 -07:00
|
|
|
tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
|
2019-06-07 10:18:03 +01:00
|
|
|
} else if infer_args {
|
2022-08-07 21:03:28 +02:00
|
|
|
self.astconv.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.
|
2020-05-05 23:02:09 -05:00
|
|
|
tcx.ty_error().into()
|
2018-05-14 18:27:13 +01:00
|
|
|
}
|
2018-05-15 13:15:49 +01:00
|
|
|
}
|
2020-08-11 00:02:45 +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");
|
2022-11-02 14:47:48 +09:00
|
|
|
if ty.references_error() {
|
|
|
|
return tcx.const_error(ty).into();
|
|
|
|
}
|
2020-08-11 00:02:45 +00:00
|
|
|
if !infer_args && has_default {
|
2023-01-10 12:27:41 -07:00
|
|
|
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
|
2020-08-11 00:02:45 +00:00
|
|
|
} else {
|
2021-03-01 12:50:09 +01:00
|
|
|
if infer_args {
|
|
|
|
self.astconv.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.
|
|
|
|
tcx.const_error(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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut substs_ctx = SubstsForAstPathCtxt {
|
|
|
|
astconv: self,
|
|
|
|
def_id,
|
|
|
|
span,
|
|
|
|
generic_args,
|
|
|
|
inferred_params: vec![],
|
|
|
|
infer_args,
|
|
|
|
};
|
2023-01-11 19:07:03 +00:00
|
|
|
let substs = create_substs_for_generic_args(
|
2020-11-13 15:49:17 +01:00
|
|
|
tcx,
|
|
|
|
def_id,
|
|
|
|
parent_substs,
|
|
|
|
self_ty.is_some(),
|
|
|
|
self_ty,
|
2020-10-26 14:18:31 -04:00
|
|
|
&arg_count,
|
2020-11-13 15:49:17 +01:00
|
|
|
&mut substs_ctx,
|
2018-07-24 17:47:31 +01:00
|
|
|
);
|
2019-12-12 17:26:19 -08:00
|
|
|
|
2022-11-04 16:28:01 +00:00
|
|
|
if let ty::BoundConstness::ConstIfConst = constness
|
2022-10-20 09:39:09 +00:00
|
|
|
&& generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
|
|
|
|
{
|
2022-10-25 18:28:04 +00:00
|
|
|
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
|
2022-10-20 09:39:09 +00:00
|
|
|
}
|
|
|
|
|
2020-10-26 14:18:31 -04:00
|
|
|
(substs, arg_count)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_assoc_bindings_for_generic_args<'a>(
|
|
|
|
&self,
|
|
|
|
generic_args: &'a hir::GenericArgs<'_>,
|
|
|
|
) -> Vec<ConvertedBinding<'a, 'tcx>> {
|
2019-05-08 15:58:20 -04:00
|
|
|
// Convert associated-type bindings or constraints into a separate vector.
|
|
|
|
// Example: Given this:
|
|
|
|
//
|
|
|
|
// T: Iterator<Item = u32>
|
|
|
|
//
|
|
|
|
// The `T` is passed in as a self-type; the `Item = u32` is
|
|
|
|
// not a "type parameter" of the `Iterator` trait, but rather
|
|
|
|
// a restriction on `<T as Iterator>::Item`, so it is passed
|
|
|
|
// back separately.
|
2019-12-24 17:38:22 -05:00
|
|
|
let assoc_bindings = generic_args
|
|
|
|
.bindings
|
|
|
|
.iter()
|
2019-03-16 00:04:02 +00:00
|
|
|
.map(|binding| {
|
2023-01-09 16:30:40 +00:00
|
|
|
let kind = match &binding.kind {
|
|
|
|
hir::TypeBindingKind::Equality { term } => match term {
|
|
|
|
hir::Term::Ty(ty) => {
|
2022-01-10 23:39:21 +00:00
|
|
|
ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into())
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::Term::Const(c) => {
|
2022-11-06 19:17:57 +00:00
|
|
|
let c = Const::from_anon_const(self.tcx(), c.def_id);
|
2022-01-10 23:39:21 +00:00
|
|
|
ConvertedBindingKind::Equality(c.into())
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
|
|
|
},
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TypeBindingKind::Constraint { bounds } => {
|
2019-12-24 17:38:22 -05:00
|
|
|
ConvertedBindingKind::Constraint(bounds)
|
|
|
|
}
|
2019-03-16 00:04:02 +00:00
|
|
|
};
|
2020-11-30 09:26:22 +01:00
|
|
|
ConvertedBinding {
|
2021-02-18 21:01:44 +01:00
|
|
|
hir_id: binding.hir_id,
|
2020-11-30 09:26:22 +01:00
|
|
|
item_name: binding.ident,
|
|
|
|
kind,
|
|
|
|
gen_args: binding.gen_args,
|
|
|
|
span: binding.span,
|
|
|
|
}
|
2019-03-16 00:04:02 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2015-09-14 02:33:29 -06:00
|
|
|
|
2020-10-26 14:18:31 -04:00
|
|
|
assoc_bindings
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2014-11-29 17:08:30 +13:00
|
|
|
|
2022-10-20 17:51:37 +02:00
|
|
|
pub fn create_substs_for_associated_item(
|
2019-12-08 17:04:17 +00:00
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
item_def_id: DefId,
|
2019-12-01 16:08:58 +01:00
|
|
|
item_segment: &hir::PathSegment<'_>,
|
2019-12-08 17:04:17 +00:00
|
|
|
parent_substs: SubstsRef<'tcx>,
|
|
|
|
) -> SubstsRef<'tcx> {
|
2021-02-18 21:01:44 +01:00
|
|
|
debug!(
|
|
|
|
"create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
|
|
|
|
span, item_def_id, item_segment
|
|
|
|
);
|
2022-09-27 00:45:50 +00:00
|
|
|
let (args, _) = self.create_substs_for_ast_path(
|
2022-08-22 04:28:40 +00:00
|
|
|
span,
|
|
|
|
item_def_id,
|
|
|
|
parent_substs,
|
|
|
|
item_segment,
|
|
|
|
item_segment.args(),
|
|
|
|
item_segment.infer_args,
|
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2022-09-27 00:45:50 +00:00
|
|
|
);
|
|
|
|
|
2022-09-29 22:44:24 +00:00
|
|
|
if let Some(b) = item_segment.args().bindings.first() {
|
2023-01-11 19:07:03 +00:00
|
|
|
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
2022-09-27 00:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
args
|
2019-12-08 17:04:17 +00:00
|
|
|
}
|
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
/// Instantiates the path for the given trait reference, assuming that it's
|
2019-05-20 16:19:34 +01:00
|
|
|
/// bound to a valid trait type. Returns the `DefId` of the defining trait.
|
2018-02-22 17:50:06 -06:00
|
|
|
/// The type _cannot_ be a type other than a trait type.
|
2016-05-11 08:48:12 +03:00
|
|
|
///
|
2019-02-08 14:53:55 +01:00
|
|
|
/// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>`
|
2016-05-11 08:48:12 +03:00
|
|
|
/// are disallowed. Otherwise, they are pushed onto the vector given.
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn instantiate_mono_trait_ref(
|
|
|
|
&self,
|
2019-12-01 16:08:58 +01:00
|
|
|
trait_ref: &hir::TraitRef<'_>,
|
2019-12-24 17:38:22 -05:00
|
|
|
self_ty: Ty<'tcx>,
|
2022-10-20 09:39:09 +00:00
|
|
|
constness: ty::BoundConstness,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> ty::TraitRef<'tcx> {
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
2017-05-15 15:21:01 +09:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
self.ast_path_to_mono_trait_ref(
|
|
|
|
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,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-02-15 15:09:26 -05:00
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
fn instantiate_poly_trait_ref_inner(
|
|
|
|
&self,
|
|
|
|
hir_id: hir::HirId,
|
|
|
|
span: Span,
|
|
|
|
binding_span: Option<Span>,
|
|
|
|
constness: ty::BoundConstness,
|
|
|
|
bounds: &mut Bounds<'tcx>,
|
|
|
|
speculative: bool,
|
|
|
|
trait_ref_span: Span,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
trait_segment: &hir::PathSegment<'_>,
|
|
|
|
args: &GenericArgs<'_>,
|
|
|
|
infer_args: bool,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
) -> GenericArgCountResult {
|
|
|
|
let (substs, arg_count) = self.create_substs_for_ast_path(
|
|
|
|
trait_ref_span,
|
|
|
|
trait_def_id,
|
|
|
|
&[],
|
|
|
|
trait_segment,
|
|
|
|
args,
|
|
|
|
infer_args,
|
|
|
|
Some(self_ty),
|
2022-11-04 16:28:01 +00:00
|
|
|
constness,
|
2021-08-15 04:17:36 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let bound_vars = tcx.late_bound_vars(hir_id);
|
|
|
|
debug!(?bound_vars);
|
|
|
|
|
|
|
|
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
|
|
|
|
|
|
|
|
let poly_trait_ref =
|
2022-12-13 11:25:31 +00:00
|
|
|
ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
|
2021-08-15 04:17:36 -04:00
|
|
|
|
|
|
|
debug!(?poly_trait_ref, ?assoc_bindings);
|
2022-12-26 04:19:27 +00:00
|
|
|
bounds.push_trait_bound(tcx, poly_trait_ref, span, constness);
|
2021-08-15 04:17:36 -04:00
|
|
|
|
|
|
|
let mut dup_bindings = FxHashMap::default();
|
|
|
|
for binding in &assoc_bindings {
|
|
|
|
// Specify type to assert that error was already reported in `Err` case.
|
2022-01-23 12:34:26 -06:00
|
|
|
let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding(
|
2021-08-15 04:17:36 -04:00
|
|
|
hir_id,
|
|
|
|
poly_trait_ref,
|
|
|
|
binding,
|
|
|
|
bounds,
|
|
|
|
speculative,
|
|
|
|
&mut dup_bindings,
|
|
|
|
binding_span.unwrap_or(binding.span),
|
2022-10-20 09:39:09 +00:00
|
|
|
constness,
|
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
|
|
|
|
}
|
|
|
|
|
2020-10-26 14:18:31 -04:00
|
|
|
/// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
|
|
|
|
/// a full trait reference. The resulting trait reference is returned. This may also generate
|
|
|
|
/// auxiliary bounds, which are added to `bounds`.
|
|
|
|
///
|
|
|
|
/// Example:
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (illustrative)
|
2020-10-26 14:18:31 -04:00
|
|
|
/// poly_trait_ref = Iterator<Item = u32>
|
|
|
|
/// self_ty = Foo
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
|
|
|
|
///
|
|
|
|
/// **A note on binders:** against our usual convention, there is an implied bounder around
|
|
|
|
/// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
|
|
|
|
/// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
|
|
|
|
/// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
|
|
|
|
/// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
|
|
|
|
/// however.
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
|
2021-08-15 04:17:36 -04:00
|
|
|
pub(crate) fn instantiate_poly_trait_ref(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2019-12-01 16:08:58 +01:00
|
|
|
trait_ref: &hir::TraitRef<'_>,
|
2019-06-18 00:02:26 +01:00
|
|
|
span: Span,
|
2021-08-27 05:02:23 +00:00
|
|
|
constness: ty::BoundConstness,
|
2016-08-04 15:52:57 +03:00
|
|
|
self_ty: Ty<'tcx>,
|
2019-03-16 00:04:02 +00:00
|
|
|
bounds: &mut Bounds<'tcx>,
|
2019-02-28 22:43:53 +00:00
|
|
|
speculative: bool,
|
2020-05-21 19:51:39 +01:00
|
|
|
) -> GenericArgCountResult {
|
2021-08-15 04:17:36 -04:00
|
|
|
let hir_id = trait_ref.hir_ref_id;
|
|
|
|
let binding_span = None;
|
|
|
|
let trait_ref_span = trait_ref.path.span;
|
2020-03-23 20:27:59 +01:00
|
|
|
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
2021-08-15 04:17:36 -04:00
|
|
|
let trait_segment = trait_ref.path.segments.last().unwrap();
|
|
|
|
let args = trait_segment.args();
|
|
|
|
let infer_args = trait_segment.infer_args;
|
2017-01-24 17:17:06 +02:00
|
|
|
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
2022-01-12 23:13:52 +01:00
|
|
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
2017-05-15 15:21:01 +09:00
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
self.instantiate_poly_trait_ref_inner(
|
|
|
|
hir_id,
|
|
|
|
span,
|
|
|
|
binding_span,
|
|
|
|
constness,
|
|
|
|
bounds,
|
|
|
|
speculative,
|
|
|
|
trait_ref_span,
|
2018-11-08 18:54:34 -08:00
|
|
|
trait_def_id,
|
2021-08-15 04:17:36 -04:00
|
|
|
trait_segment,
|
|
|
|
args,
|
|
|
|
infer_args,
|
2018-11-08 18:54:34 -08:00
|
|
|
self_ty,
|
2021-08-15 04:17:36 -04:00
|
|
|
)
|
2015-02-15 15:09:26 -05:00
|
|
|
}
|
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
pub(crate) fn instantiate_lang_item_trait_ref(
|
2020-08-04 14:34:24 +01:00
|
|
|
&self,
|
|
|
|
lang_item: hir::LangItem,
|
|
|
|
span: Span,
|
|
|
|
hir_id: hir::HirId,
|
|
|
|
args: &GenericArgs<'_>,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
bounds: &mut Bounds<'tcx>,
|
|
|
|
) {
|
2021-08-15 04:17:36 -04:00
|
|
|
let binding_span = Some(span);
|
|
|
|
let constness = ty::BoundConstness::NotConst;
|
|
|
|
let speculative = false;
|
|
|
|
let trait_ref_span = span;
|
2020-08-04 14:34:24 +01:00
|
|
|
let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
|
2021-08-15 04:17:36 -04:00
|
|
|
let trait_segment = &hir::PathSegment::invalid();
|
|
|
|
let infer_args = false;
|
2020-08-04 14:34:24 +01:00
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
self.instantiate_poly_trait_ref_inner(
|
|
|
|
hir_id,
|
2021-01-02 19:45:11 +01:00
|
|
|
span,
|
2021-08-15 04:17:36 -04:00
|
|
|
binding_span,
|
|
|
|
constness,
|
|
|
|
bounds,
|
|
|
|
speculative,
|
|
|
|
trait_ref_span,
|
2021-01-02 19:45:11 +01:00
|
|
|
trait_def_id,
|
2021-08-15 04:17:36 -04:00
|
|
|
trait_segment,
|
2021-01-02 19:45:11 +01:00
|
|
|
args,
|
2021-08-15 04:17:36 -04:00
|
|
|
infer_args,
|
|
|
|
self_ty,
|
2021-01-02 19:45:11 +01:00
|
|
|
);
|
2020-08-04 14:34:24 +01:00
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
fn ast_path_to_mono_trait_ref(
|
|
|
|
&self,
|
2019-03-16 00:04:02 +00:00
|
|
|
span: Span,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
self_ty: Ty<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
trait_segment: &hir::PathSegment<'_>,
|
2022-01-12 23:13:52 +01:00
|
|
|
is_impl: bool,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness: ty::BoundConstness,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> ty::TraitRef<'tcx> {
|
2022-01-12 23:13:52 +01:00
|
|
|
let (substs, _) = self.create_substs_for_ast_trait_ref(
|
|
|
|
span,
|
|
|
|
trait_def_id,
|
|
|
|
self_ty,
|
|
|
|
trait_segment,
|
|
|
|
is_impl,
|
2022-10-20 09:39:09 +00:00
|
|
|
constness,
|
2022-01-12 23:13:52 +01:00
|
|
|
);
|
2022-09-29 22:44:24 +00:00
|
|
|
if let Some(b) = trait_segment.args().bindings.first() {
|
2023-01-11 19:07:03 +00:00
|
|
|
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
2020-04-24 13:58:41 -07:00
|
|
|
}
|
2022-12-13 11:25:31 +00:00
|
|
|
self.tcx().mk_trait_ref(trait_def_id, substs)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-02-15 15:09:26 -05:00
|
|
|
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self, span))]
|
2019-12-18 11:12:50 -08:00
|
|
|
fn create_substs_for_ast_trait_ref<'a>(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
self_ty: Ty<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
trait_segment: &'a hir::PathSegment<'a>,
|
2022-01-12 23:13:52 +01:00
|
|
|
is_impl: bool,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness: ty::BoundConstness,
|
2020-10-26 14:18:31 -04:00
|
|
|
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
|
2022-01-12 23:13:52 +01:00
|
|
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
2014-11-15 17:09:51 -05:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
self.create_substs_for_ast_path(
|
|
|
|
span,
|
|
|
|
trait_def_id,
|
|
|
|
&[],
|
2021-01-02 19:45:11 +01:00
|
|
|
trait_segment,
|
|
|
|
trait_segment.args(),
|
2019-12-24 17:38:22 -05:00
|
|
|
trait_segment.infer_args,
|
|
|
|
Some(self_ty),
|
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
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2020-04-19 13:00:18 +02:00
|
|
|
fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
2020-02-17 13:09:01 -08:00
|
|
|
self.tcx()
|
|
|
|
.associated_items(trait_def_id)
|
|
|
|
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
|
|
|
|
.is_some()
|
2016-11-10 02:06:34 +02:00
|
|
|
}
|
2022-02-02 16:42:37 +00:00
|
|
|
fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
2022-01-10 23:39:21 +00:00
|
|
|
self.tcx()
|
|
|
|
.associated_items(trait_def_id)
|
2022-02-02 16:42:37 +00:00
|
|
|
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
|
2022-01-10 23:39:21 +00:00
|
|
|
.is_some()
|
|
|
|
}
|
2016-11-10 02:06:34 +02:00
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Sets `implicitly_sized` to true on `Bounds` if necessary
|
2022-12-26 04:19:27 +00:00
|
|
|
pub(crate) fn add_implicitly_sized(
|
2021-08-15 00:53:40 -04:00
|
|
|
&self,
|
2022-12-26 04:19:27 +00:00
|
|
|
bounds: &mut Bounds<'tcx>,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
|
|
|
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
2021-08-15 00:53:40 -04:00
|
|
|
span: Span,
|
2021-08-15 03:09:47 -04:00
|
|
|
) {
|
2019-03-16 00:04:02 +00:00
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
// Try to find an unbound in bounds.
|
|
|
|
let mut unbound = None;
|
2022-12-26 04:19:27 +00:00
|
|
|
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
2021-08-15 03:09:47 -04:00
|
|
|
for ab in ast_bounds {
|
|
|
|
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
|
|
|
|
if unbound.is_none() {
|
|
|
|
unbound = Some(&ptr.trait_ref);
|
|
|
|
} else {
|
|
|
|
tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
|
|
|
|
}
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-15 03:09:47 -04:00
|
|
|
};
|
|
|
|
search_bounds(ast_bounds);
|
|
|
|
if let Some((self_ty, where_clause)) = self_ty_where_predicates {
|
2021-08-15 00:53:40 -04:00
|
|
|
for clause in where_clause {
|
2021-09-30 19:38:50 +02:00
|
|
|
if let hir::WherePredicate::BoundPredicate(pred) = clause {
|
2022-11-06 18:26:36 +00:00
|
|
|
if pred.is_param_bound(self_ty.to_def_id()) {
|
2022-02-07 22:58:30 +01:00
|
|
|
search_bounds(pred.bounds);
|
2021-08-15 00:53:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-16 00:04:02 +00:00
|
|
|
|
2022-10-26 17:01:00 -05:00
|
|
|
let sized_def_id = tcx.lang_items().sized_trait();
|
2021-08-15 03:09:47 -04:00
|
|
|
match (&sized_def_id, unbound) {
|
2022-10-26 17:01:00 -05:00
|
|
|
(Some(sized_def_id), Some(tpb))
|
2021-08-15 03:09:47 -04:00
|
|
|
if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
|
|
|
|
{
|
|
|
|
// There was in fact a `?Sized` bound, return without doing anything
|
|
|
|
return;
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
2021-08-15 03:09:47 -04:00
|
|
|
(_, Some(_)) => {
|
|
|
|
// There was a `?Trait` bound, but it was not `?Sized`; warn.
|
|
|
|
tcx.sess.span_warn(
|
|
|
|
span,
|
|
|
|
"default bound relaxed for a type parameter, but \
|
|
|
|
this does nothing because the given bound is not \
|
|
|
|
a default; only `?Sized` is supported",
|
|
|
|
);
|
|
|
|
// Otherwise, add implicitly sized if `Sized` is available.
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
2021-08-15 03:09:47 -04:00
|
|
|
_ => {
|
|
|
|
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
|
|
|
}
|
|
|
|
}
|
2022-10-26 17:01:00 -05:00
|
|
|
if sized_def_id.is_none() {
|
2019-03-16 00:04:02 +00:00
|
|
|
// No lang item for `Sized`, so we can't add it as a bound.
|
2021-08-15 03:09:47 -04:00
|
|
|
return;
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
2022-12-26 04:19:27 +00:00
|
|
|
bounds.push_sized(tcx, self_ty, span);
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
|
|
|
|
2019-05-31 17:30:44 -04:00
|
|
|
/// This helper takes a *converted* parameter type (`param_ty`)
|
|
|
|
/// and an *unconverted* list of bounds:
|
|
|
|
///
|
2020-04-18 18:39:40 +02:00
|
|
|
/// ```text
|
2019-05-31 17:30:44 -04:00
|
|
|
/// fn foo<T: Debug>
|
|
|
|
/// ^ ^^^^^ `ast_bounds` parameter, in HIR form
|
|
|
|
/// |
|
|
|
|
/// `param_ty`, in ty form
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// It adds these `ast_bounds` into the `bounds` structure.
|
|
|
|
///
|
2019-06-05 15:20:40 -04:00
|
|
|
/// **A note on binders:** there is an implied binder around
|
2019-05-31 17:30:44 -04:00
|
|
|
/// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
|
|
|
|
/// for more details.
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self, ast_bounds, bounds))]
|
2021-08-15 04:17:36 -04:00
|
|
|
pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2019-03-16 00:04:02 +00:00
|
|
|
param_ty: Ty<'tcx>,
|
2021-08-15 04:17:36 -04:00
|
|
|
ast_bounds: I,
|
2019-03-16 00:04:02 +00:00
|
|
|
bounds: &mut Bounds<'tcx>,
|
2020-10-26 14:18:31 -04:00
|
|
|
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
2019-03-16 00:04:02 +00:00
|
|
|
) {
|
|
|
|
for ast_bound in ast_bounds {
|
2021-08-15 04:17:36 -04:00
|
|
|
match ast_bound {
|
|
|
|
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
|
|
|
let constness = match modifier {
|
|
|
|
hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
|
|
|
|
hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
|
|
|
|
hir::TraitBoundModifier::Maybe => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
let _ = self.instantiate_poly_trait_ref(
|
|
|
|
&poly_trait_ref.trait_ref,
|
|
|
|
poly_trait_ref.span,
|
|
|
|
constness,
|
2020-10-26 14:18:31 -04:00
|
|
|
param_ty,
|
|
|
|
bounds,
|
|
|
|
false,
|
|
|
|
);
|
2020-01-13 20:30:33 -08:00
|
|
|
}
|
2021-08-15 04:17:36 -04:00
|
|
|
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
|
|
|
|
self.instantiate_lang_item_trait_ref(
|
|
|
|
lang_item, span, hir_id, args, param_ty, bounds,
|
2020-10-26 14:18:31 -04:00
|
|
|
);
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2021-08-15 04:17:36 -04:00
|
|
|
hir::GenericBound::Outlives(lifetime) => {
|
|
|
|
let region = self.ast_region_to_region(lifetime, None);
|
2022-12-26 04:19:27 +00:00
|
|
|
bounds.push_region_bound(
|
|
|
|
self.tcx(),
|
|
|
|
ty::Binder::bind_with_vars(
|
|
|
|
ty::OutlivesPredicate(param_ty, region),
|
|
|
|
bound_vars,
|
|
|
|
),
|
2022-11-05 22:41:07 +00:00
|
|
|
lifetime.ident.span,
|
2022-12-26 04:19:27 +00:00
|
|
|
);
|
2021-08-15 04:17:36 -04:00
|
|
|
}
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 17:30:44 -04:00
|
|
|
/// Translates a list of bounds from the HIR into the `Bounds` data structure.
|
|
|
|
/// The self-type for the bounds is given by `param_ty`.
|
|
|
|
///
|
|
|
|
/// Example:
|
|
|
|
///
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (illustrative)
|
2019-05-31 17:30:44 -04:00
|
|
|
/// fn foo<T: Bar + Baz>() { }
|
2022-04-15 15:04:34 -07:00
|
|
|
/// // ^ ^^^^^^^^^ ast_bounds
|
|
|
|
/// // param_ty
|
2019-05-31 17:30:44 -04:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
|
2022-11-16 20:34:16 +00:00
|
|
|
/// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the
|
2019-05-31 17:30:44 -04:00
|
|
|
/// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
|
|
|
|
///
|
|
|
|
/// `span` should be the declaration size of the parameter.
|
2021-08-15 00:53:40 -04:00
|
|
|
pub(crate) fn compute_bounds(
|
2019-12-24 17:38:22 -05:00
|
|
|
&self,
|
2019-03-16 00:04:02 +00:00
|
|
|
param_ty: Ty<'tcx>,
|
2019-12-01 16:08:58 +01:00
|
|
|
ast_bounds: &[hir::GenericBound<'_>],
|
2020-12-03 20:10:55 -03:00
|
|
|
) -> Bounds<'tcx> {
|
2021-09-30 19:38:50 +02:00
|
|
|
self.compute_bounds_inner(param_ty, ast_bounds)
|
2020-12-03 20:10:55 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
|
|
|
/// named `assoc_name` into ty::Bounds. Ignore the rest.
|
2021-08-15 00:53:40 -04:00
|
|
|
pub(crate) fn compute_bounds_that_match_assoc_type(
|
2020-12-03 20:10:55 -03:00
|
|
|
&self,
|
|
|
|
param_ty: Ty<'tcx>,
|
|
|
|
ast_bounds: &[hir::GenericBound<'_>],
|
|
|
|
assoc_name: Ident,
|
|
|
|
) -> Bounds<'tcx> {
|
|
|
|
let mut result = Vec::new();
|
|
|
|
|
|
|
|
for ast_bound in ast_bounds {
|
2022-02-26 07:43:47 -03:00
|
|
|
if let Some(trait_ref) = ast_bound.trait_ref()
|
|
|
|
&& let Some(trait_did) = trait_ref.trait_def_id()
|
|
|
|
&& self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
|
|
|
|
{
|
|
|
|
result.push(ast_bound.clone());
|
2020-12-03 20:10:55 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-15 03:09:47 -04:00
|
|
|
self.compute_bounds_inner(param_ty, &result)
|
2020-12-03 20:10:55 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn compute_bounds_inner(
|
|
|
|
&self,
|
|
|
|
param_ty: Ty<'tcx>,
|
2020-10-26 14:18:31 -04:00
|
|
|
ast_bounds: &[hir::GenericBound<'_>],
|
2019-03-16 00:04:02 +00:00
|
|
|
) -> Bounds<'tcx> {
|
|
|
|
let mut bounds = Bounds::default();
|
2019-03-21 17:55:09 +00:00
|
|
|
|
2021-08-15 04:17:36 -04:00
|
|
|
self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
|
2022-05-04 22:46:24 +02:00
|
|
|
debug!(?bounds);
|
2019-03-21 17:55:09 +00:00
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
bounds
|
|
|
|
}
|
|
|
|
|
2019-06-05 15:20:40 -04:00
|
|
|
/// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
|
|
|
|
/// onto `bounds`.
|
|
|
|
///
|
|
|
|
/// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
|
|
|
|
/// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
|
|
|
|
/// the binder (e.g., `&'a u32`) and hence may reference bound regions.
|
2022-08-31 13:01:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))]
|
2019-03-16 00:04:02 +00:00
|
|
|
fn add_predicates_for_ast_type_binding(
|
2016-03-22 06:37:12 -04:00
|
|
|
&self,
|
2019-02-26 15:47:14 +01:00
|
|
|
hir_ref_id: hir::HirId,
|
2016-08-04 15:52:57 +03:00
|
|
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
2019-06-12 11:43:15 +03:00
|
|
|
binding: &ConvertedBinding<'_, 'tcx>,
|
2019-03-16 00:04:02 +00:00
|
|
|
bounds: &mut Bounds<'tcx>,
|
2018-11-06 23:17:11 +00:00
|
|
|
speculative: bool,
|
2019-03-16 00:04:02 +00:00
|
|
|
dup_bindings: &mut FxHashMap<DefId, Span>,
|
2019-12-12 15:22:46 -08:00
|
|
|
path_span: Span,
|
2022-10-20 09:39:09 +00:00
|
|
|
constness: ty::BoundConstness,
|
2022-01-23 12:34:26 -06:00
|
|
|
) -> Result<(), ErrorGuaranteed> {
|
2020-11-30 09:26:22 +01:00
|
|
|
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
|
|
|
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
|
|
|
// subtle in the event that `T` is defined in a supertrait of
|
|
|
|
// `SomeTrait`, because in that case we need to upcast.
|
|
|
|
//
|
|
|
|
// That is, consider this case:
|
|
|
|
//
|
|
|
|
// ```
|
|
|
|
// trait SubTrait: SuperTrait<i32> { }
|
|
|
|
// trait SuperTrait<A> { type T; }
|
|
|
|
//
|
|
|
|
// ... B: SubTrait<T = foo> ...
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// We want to produce `<B as SuperTrait<i32>>::T == foo`.
|
2020-07-22 22:54:06 -07:00
|
|
|
|
2020-11-30 09:26:22 +01:00
|
|
|
let tcx = self.tcx();
|
2016-03-22 06:37:12 -04:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let candidate =
|
|
|
|
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
|
|
|
|
// Simple case: X is defined in the current trait.
|
2019-12-12 21:15:19 -08:00
|
|
|
trait_ref
|
2019-12-24 17:38:22 -05:00
|
|
|
} else {
|
|
|
|
// Otherwise, we have to walk through the supertraits to find
|
|
|
|
// those that do.
|
|
|
|
self.one_bound_for_assoc_type(
|
|
|
|
|| traits::supertraits(tcx, trait_ref),
|
2020-01-02 00:19:29 +01:00
|
|
|
|| trait_ref.print_only_trait_path().to_string(),
|
2019-12-24 17:38:22 -05:00
|
|
|
binding.item_name,
|
2019-12-12 15:22:46 -08:00
|
|
|
path_span,
|
2020-01-02 00:19:29 +01:00
|
|
|
|| match binding.kind {
|
2019-12-12 21:15:19 -08:00
|
|
|
ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
)?
|
|
|
|
};
|
2017-11-18 18:38:56 +03:00
|
|
|
|
2018-05-26 02:50:15 +03:00
|
|
|
let (assoc_ident, def_scope) =
|
2019-05-28 07:43:05 +10:00
|
|
|
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
|
2020-02-17 13:09:01 -08:00
|
|
|
|
2020-03-14 01:36:46 +03:00
|
|
|
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
|
2020-02-17 13:35:49 -08:00
|
|
|
// of calling `filter_by_name_and_kind`.
|
2022-02-02 16:42:37 +00:00
|
|
|
let find_item_of_kind = |kind| {
|
|
|
|
tcx.associated_items(candidate.def_id())
|
|
|
|
.filter_by_name_unhygienic(assoc_ident.name)
|
|
|
|
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
|
|
|
|
};
|
|
|
|
let assoc_item = find_item_of_kind(ty::AssocKind::Type)
|
|
|
|
.or_else(|| find_item_of_kind(ty::AssocKind::Const))
|
2019-12-24 17:38:22 -05:00
|
|
|
.expect("missing associated type");
|
2017-11-18 18:38:56 +03:00
|
|
|
|
2022-03-12 21:40:43 +01:00
|
|
|
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
|
2020-03-22 15:36:54 -07:00
|
|
|
tcx.sess
|
|
|
|
.struct_span_err(
|
|
|
|
binding.span,
|
2022-07-24 19:33:26 +00:00
|
|
|
&format!("{} `{}` is private", assoc_item.kind, binding.item_name),
|
2020-03-22 15:36:54 -07:00
|
|
|
)
|
2022-07-24 19:33:26 +00:00
|
|
|
.span_label(binding.span, &format!("private {}", assoc_item.kind))
|
2020-03-22 15:36:54 -07:00
|
|
|
.emit();
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2022-01-27 14:40:38 +00:00
|
|
|
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
|
2016-05-11 08:48:12 +03:00
|
|
|
|
2018-11-06 23:17:11 +00:00
|
|
|
if !speculative {
|
2019-12-24 17:38:22 -05:00
|
|
|
dup_bindings
|
2022-01-27 14:40:38 +00:00
|
|
|
.entry(assoc_item.def_id)
|
2018-11-06 23:17:11 +00:00
|
|
|
.and_modify(|prev_span| {
|
2020-08-27 20:09:22 +10:00
|
|
|
self.tcx().sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
|
|
|
|
span: binding.span,
|
|
|
|
prev_span: *prev_span,
|
|
|
|
item_name: binding.item_name,
|
2022-03-13 00:52:25 +01:00
|
|
|
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
|
2020-08-27 20:09:22 +10:00
|
|
|
});
|
2018-11-06 23:17:11 +00:00
|
|
|
})
|
|
|
|
.or_insert(binding.span);
|
|
|
|
}
|
|
|
|
|
2020-11-30 09:26:22 +01:00
|
|
|
// Include substitutions for generic parameters of associated types
|
|
|
|
let projection_ty = candidate.map_bound(|trait_ref| {
|
2022-01-27 14:40:38 +00:00
|
|
|
let ident = Ident::new(assoc_item.name, binding.item_name.span);
|
2020-11-30 09:26:22 +01:00
|
|
|
let item_segment = hir::PathSegment {
|
2021-02-18 21:01:44 +01:00
|
|
|
ident,
|
2022-08-30 16:54:42 +10:00
|
|
|
hir_id: binding.hir_id,
|
2022-08-30 15:10:28 +10:00
|
|
|
res: Res::Err,
|
2020-11-30 09:26:22 +01:00
|
|
|
args: Some(binding.gen_args),
|
|
|
|
infer_args: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
|
|
|
|
path_span,
|
2022-01-27 14:40:38 +00:00
|
|
|
assoc_item.def_id,
|
2020-11-30 09:26:22 +01:00
|
|
|
&item_segment,
|
|
|
|
trait_ref.substs,
|
|
|
|
);
|
|
|
|
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?substs_trait_ref_and_assoc_item);
|
2020-11-30 09:26:22 +01:00
|
|
|
|
2022-12-13 10:25:21 +00:00
|
|
|
self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
|
2020-11-30 09:26:22 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
if !speculative {
|
|
|
|
// Find any late-bound regions declared in `ty` that are not
|
2022-01-27 14:40:38 +00:00
|
|
|
// declared in the trait-ref or assoc_item. These are not well-formed.
|
2020-11-30 09:26:22 +01:00
|
|
|
//
|
|
|
|
// Example:
|
|
|
|
//
|
|
|
|
// for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
|
|
|
|
// for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
|
|
|
|
if let ConvertedBindingKind::Equality(ty) = binding.kind {
|
|
|
|
let late_bound_in_trait_ref =
|
|
|
|
tcx.collect_constrained_late_bound_regions(&projection_ty);
|
|
|
|
let late_bound_in_ty =
|
2021-01-07 00:41:55 -05:00
|
|
|
tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty));
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?late_bound_in_trait_ref);
|
|
|
|
debug!(?late_bound_in_ty);
|
2020-11-30 09:26:22 +01:00
|
|
|
|
|
|
|
// FIXME: point at the type params that don't have appropriate lifetimes:
|
|
|
|
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
|
|
|
// ---- ---- ^^^^^^^
|
|
|
|
self.validate_late_bound_regions(
|
|
|
|
late_bound_in_trait_ref,
|
|
|
|
late_bound_in_ty,
|
|
|
|
|br_name| {
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
binding.span,
|
|
|
|
E0582,
|
|
|
|
"binding for associated type `{}` references {}, \
|
|
|
|
which does not appear in the trait input types",
|
|
|
|
binding.item_name,
|
|
|
|
br_name
|
|
|
|
)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
match binding.kind {
|
2022-07-29 05:48:40 +00:00
|
|
|
ConvertedBindingKind::Equality(mut term) => {
|
2019-05-08 15:58:20 -04:00
|
|
|
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
|
|
|
|
// the "projection predicate" for:
|
|
|
|
//
|
|
|
|
// `<T as Iterator>::Item = u32`
|
2022-11-26 21:21:20 +00:00
|
|
|
let assoc_item_def_id = projection_ty.skip_binder().def_id;
|
2022-02-01 15:28:31 +00:00
|
|
|
let def_kind = tcx.def_kind(assoc_item_def_id);
|
2022-09-05 14:03:53 +10:00
|
|
|
match (def_kind, term.unpack()) {
|
|
|
|
(hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
|
|
|
|
| (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (),
|
2022-01-28 18:14:27 +00:00
|
|
|
(_, _) => {
|
2022-09-05 14:03:53 +10:00
|
|
|
let got = if let Some(_) = term.ty() { "type" } else { "constant" };
|
2022-02-01 15:28:31 +00:00
|
|
|
let expected = def_kind.descr(assoc_item_def_id);
|
2022-12-30 05:09:09 +00:00
|
|
|
let mut err = tcx.sess.struct_span_err(
|
|
|
|
binding.span,
|
|
|
|
&format!("expected {expected} bound, found {got}"),
|
|
|
|
);
|
|
|
|
err.span_note(
|
|
|
|
tcx.def_span(assoc_item_def_id),
|
|
|
|
&format!("{expected} defined here"),
|
|
|
|
);
|
|
|
|
|
|
|
|
if let hir::def::DefKind::AssocConst = def_kind
|
|
|
|
&& let Some(t) = term.ty() && (t.is_enum() || t.references_error())
|
|
|
|
&& tcx.features().associated_const_equality {
|
|
|
|
err.span_suggestion(
|
2022-01-28 18:14:27 +00:00
|
|
|
binding.span,
|
2022-12-30 05:09:09 +00:00
|
|
|
"if equating a const, try wrapping with braces",
|
|
|
|
format!("{} = {{ const }}", binding.item_name),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
let reported = err.emit();
|
2022-07-29 05:48:40 +00:00
|
|
|
term = match def_kind {
|
2022-11-03 14:15:17 +08:00
|
|
|
hir::def::DefKind::AssocTy => {
|
|
|
|
tcx.ty_error_with_guaranteed(reported).into()
|
|
|
|
}
|
2022-07-29 05:48:40 +00:00
|
|
|
hir::def::DefKind::AssocConst => tcx
|
2022-11-03 14:15:17 +08:00
|
|
|
.const_error_with_guaranteed(
|
2023-02-07 01:29:48 -07:00
|
|
|
tcx.type_of(assoc_item_def_id)
|
2022-07-29 05:48:40 +00:00
|
|
|
.subst(tcx, projection_ty.skip_binder().substs),
|
2022-11-03 14:15:17 +08:00
|
|
|
reported,
|
2022-07-29 05:48:40 +00:00
|
|
|
)
|
|
|
|
.into(),
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2022-01-28 18:14:27 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-26 04:19:27 +00:00
|
|
|
bounds.push_projection_bound(
|
|
|
|
tcx,
|
|
|
|
projection_ty
|
|
|
|
.map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }),
|
2021-07-30 08:56:45 +00:00
|
|
|
binding.span,
|
2022-12-26 04:19:27 +00:00
|
|
|
);
|
2021-07-30 08:56:45 +00:00
|
|
|
}
|
2019-06-12 11:43:15 +03:00
|
|
|
ConvertedBindingKind::Constraint(ast_bounds) => {
|
2019-05-08 15:58:42 -04:00
|
|
|
// "Desugar" a constraint like `T: Iterator<Item: Debug>` to
|
|
|
|
//
|
|
|
|
// `<T as Iterator>::Item: Debug`
|
|
|
|
//
|
2019-06-05 15:27:19 -04:00
|
|
|
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
|
|
|
|
// parameter to have a skipped binder.
|
2023-02-08 12:28:03 +11:00
|
|
|
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
|
2021-08-15 04:17:36 -04:00
|
|
|
self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
|
2019-03-16 00:04:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
2015-01-05 05:36:41 -05:00
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
fn ast_path_to_ty(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
did: DefId,
|
|
|
|
item_segment: &hir::PathSegment<'_>,
|
|
|
|
) -> Ty<'tcx> {
|
2017-01-21 17:40:31 +03:00
|
|
|
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
|
2023-02-07 01:29:48 -07:00
|
|
|
self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
|
2014-02-02 00:09:11 +11:00
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
fn conv_object_ty_poly_trait_ref(
|
|
|
|
&self,
|
2019-04-29 03:58:24 +01:00
|
|
|
span: Span,
|
2022-12-26 04:19:27 +00:00
|
|
|
hir_trait_bounds: &[hir::PolyTraitRef<'_>],
|
2019-12-24 17:38:22 -05:00
|
|
|
lifetime: &hir::Lifetime,
|
2020-08-13 18:30:00 -07:00
|
|
|
borrowed: bool,
|
2022-08-29 03:53:33 +00:00
|
|
|
representation: DynKind,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> Ty<'tcx> {
|
2019-03-28 01:29:31 +00:00
|
|
|
let tcx = self.tcx();
|
|
|
|
|
2019-03-16 00:04:02 +00:00
|
|
|
let mut bounds = Bounds::default();
|
2019-04-29 03:58:24 +01:00
|
|
|
let mut potential_assoc_types = Vec::new();
|
|
|
|
let dummy_self = self.tcx().types.trait_object_dummy_self;
|
2022-12-26 04:19:27 +00:00
|
|
|
for trait_bound in hir_trait_bounds.iter().rev() {
|
2020-05-21 19:51:39 +01:00
|
|
|
if let GenericArgCountResult {
|
|
|
|
correct:
|
|
|
|
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
|
|
|
..
|
|
|
|
} = self.instantiate_poly_trait_ref(
|
2020-10-26 14:18:31 -04:00
|
|
|
&trait_bound.trait_ref,
|
|
|
|
trait_bound.span,
|
2021-08-27 05:02:23 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2020-01-13 20:30:33 -08:00
|
|
|
dummy_self,
|
|
|
|
&mut bounds,
|
2020-10-26 14:18:31 -04:00
|
|
|
false,
|
2020-02-22 01:55:35 +00:00
|
|
|
) {
|
2021-01-02 19:45:11 +01:00
|
|
|
potential_assoc_types.extend(cur_potential_assoc_types);
|
2020-02-22 01:55:35 +00:00
|
|
|
}
|
2019-06-18 00:02:26 +01:00
|
|
|
}
|
2019-04-29 03:58:24 +01:00
|
|
|
|
2022-12-26 04:19:27 +00:00
|
|
|
let mut trait_bounds = vec![];
|
|
|
|
let mut projection_bounds = vec![];
|
|
|
|
for (pred, span) in bounds.predicates() {
|
|
|
|
let bound_pred = pred.kind();
|
|
|
|
match bound_pred.skip_binder() {
|
|
|
|
ty::PredicateKind::Clause(clause) => match clause {
|
|
|
|
ty::Clause::Trait(trait_pred) => {
|
|
|
|
assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
|
|
|
|
trait_bounds.push((
|
|
|
|
bound_pred.rebind(trait_pred.trait_ref),
|
|
|
|
span,
|
|
|
|
trait_pred.constness,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
ty::Clause::Projection(proj) => {
|
|
|
|
projection_bounds.push((bound_pred.rebind(proj), span));
|
|
|
|
}
|
|
|
|
ty::Clause::TypeOutlives(_) => {
|
|
|
|
// Do nothing, we deal with regions separately
|
|
|
|
}
|
2023-02-16 11:55:58 +00:00
|
|
|
ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
|
2022-12-26 04:19:27 +00:00
|
|
|
},
|
|
|
|
ty::PredicateKind::WellFormed(_)
|
2023-02-10 13:43:29 +00:00
|
|
|
| ty::PredicateKind::AliasEq(..)
|
2022-12-26 04:19:27 +00:00
|
|
|
| ty::PredicateKind::ObjectSafe(_)
|
|
|
|
| ty::PredicateKind::ClosureKind(_, _, _)
|
|
|
|
| ty::PredicateKind::Subtype(_)
|
|
|
|
| ty::PredicateKind::Coerce(_)
|
|
|
|
| ty::PredicateKind::ConstEvaluatable(_)
|
|
|
|
| ty::PredicateKind::ConstEquate(_, _)
|
|
|
|
| ty::PredicateKind::TypeWellFormedFromEnv(_)
|
|
|
|
| ty::PredicateKind::Ambiguous => bug!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 01:29:31 +00:00
|
|
|
// Expand trait aliases recursively and check that only one regular (non-auto) trait
|
2019-04-29 03:58:24 +01:00
|
|
|
// is used and no 'maybe' bounds are used.
|
2020-02-04 02:28:11 +01:00
|
|
|
let expanded_traits =
|
2022-12-26 04:19:27 +00:00
|
|
|
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
|
|
|
|
|
2022-05-04 22:47:09 +02:00
|
|
|
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
|
|
|
|
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
|
|
|
|
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
|
2019-03-28 01:29:31 +00:00
|
|
|
if regular_traits.len() > 1 {
|
2019-05-02 18:03:29 +01:00
|
|
|
let first_trait = ®ular_traits[0];
|
|
|
|
let additional_trait = ®ular_traits[1];
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut err = struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
additional_trait.bottom().1,
|
|
|
|
E0225,
|
2019-05-02 02:21:20 +01:00
|
|
|
"only auto traits can be used as additional traits in a trait object"
|
2019-05-13 19:51:33 +01:00
|
|
|
);
|
2019-12-24 17:38:22 -05:00
|
|
|
additional_trait.label_with_exp_info(
|
|
|
|
&mut err,
|
|
|
|
"additional non-auto trait",
|
|
|
|
"additional use",
|
|
|
|
);
|
|
|
|
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
|
2020-08-14 12:08:49 -07:00
|
|
|
err.help(&format!(
|
2021-10-02 07:21:01 +07:00
|
|
|
"consider creating a new trait with all of these as supertraits and using that \
|
2020-08-14 12:08:49 -07:00
|
|
|
trait here instead: `trait NewTrait: {} {{}}`",
|
|
|
|
regular_traits
|
|
|
|
.iter()
|
|
|
|
.map(|t| t.trait_ref().print_only_trait_path().to_string())
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(" + "),
|
|
|
|
));
|
|
|
|
err.note(
|
|
|
|
"auto-traits like `Send` and `Sync` are traits that have special properties; \
|
|
|
|
for more information on them, visit \
|
|
|
|
<https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
|
|
|
|
);
|
2019-05-13 19:51:33 +01:00
|
|
|
err.emit();
|
2019-03-28 01:29:31 +00:00
|
|
|
}
|
|
|
|
|
2019-04-29 03:58:24 +01:00
|
|
|
if regular_traits.is_empty() && auto_traits.is_empty() {
|
2022-12-26 04:19:27 +00:00
|
|
|
let trait_alias_span = trait_bounds
|
2022-05-09 19:03:37 +02:00
|
|
|
.iter()
|
|
|
|
.map(|&(trait_ref, _, _)| trait_ref.def_id())
|
|
|
|
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
|
|
|
|
.map(|trait_ref| tcx.def_span(trait_ref));
|
2022-11-03 14:15:17 +08:00
|
|
|
let reported =
|
|
|
|
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
|
|
|
|
return tcx.ty_error_with_guaranteed(reported);
|
2017-01-24 17:17:06 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 03:08:04 +00:00
|
|
|
// Check that there are no gross object safety violations;
|
2018-11-01 19:43:38 +00:00
|
|
|
// most importantly, that the supertraits don't contain `Self`,
|
2018-11-01 03:08:04 +00:00
|
|
|
// to avoid ICEs.
|
2019-04-29 03:58:24 +01:00
|
|
|
for item in ®ular_traits {
|
|
|
|
let object_safety_violations =
|
2020-01-05 18:07:29 +01:00
|
|
|
astconv_object_safety_violations(tcx, item.trait_ref().def_id());
|
2019-04-29 03:58:24 +01:00
|
|
|
if !object_safety_violations.is_empty() {
|
2022-11-03 14:15:17 +08:00
|
|
|
let reported = report_object_safety_error(
|
2020-01-05 17:51:09 +01:00
|
|
|
tcx,
|
2019-04-29 03:58:24 +01:00
|
|
|
span,
|
|
|
|
item.trait_ref().def_id(),
|
2021-12-03 03:06:36 +01:00
|
|
|
&object_safety_violations,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
|
|
|
.emit();
|
2022-11-03 14:15:17 +08:00
|
|
|
return tcx.ty_error_with_guaranteed(reported);
|
2019-04-29 03:58:24 +01:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-03-16 18:45:01 +02:00
|
|
|
|
2018-11-01 19:43:38 +00:00
|
|
|
// Use a `BTreeSet` to keep output in a more consistent order.
|
2019-12-17 18:15:06 -08:00
|
|
|
let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
|
2018-08-31 16:09:04 -04:00
|
|
|
|
2022-12-26 04:19:27 +00:00
|
|
|
let regular_traits_refs_spans = trait_bounds
|
2019-04-29 03:58:24 +01:00
|
|
|
.into_iter()
|
2020-01-13 20:30:33 -08:00
|
|
|
.filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
|
|
|
|
|
|
|
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
|
2021-08-27 05:02:23 +00:00
|
|
|
assert_eq!(constness, ty::BoundConstness::NotConst);
|
2019-12-17 18:15:06 -08:00
|
|
|
|
2020-03-03 15:07:04 -08:00
|
|
|
for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
|
2019-12-17 18:15:06 -08:00
|
|
|
debug!(
|
|
|
|
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
|
2020-03-03 15:07:04 -08:00
|
|
|
obligation.predicate
|
2019-12-17 18:15:06 -08:00
|
|
|
);
|
2020-06-18 20:41:43 +02:00
|
|
|
|
2021-01-07 11:20:28 -05:00
|
|
|
let bound_predicate = obligation.predicate.kind();
|
2020-10-07 20:02:06 -04:00
|
|
|
match bound_predicate.skip_binder() {
|
2022-11-24 18:14:58 -03:00
|
|
|
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
|
2020-10-16 14:04:11 -04:00
|
|
|
let pred = bound_predicate.rebind(pred);
|
2019-12-17 18:15:06 -08:00
|
|
|
associated_types.entry(span).or_default().extend(
|
|
|
|
tcx.associated_items(pred.def_id())
|
2020-02-17 13:09:01 -08:00
|
|
|
.in_definition_order()
|
2019-12-17 18:15:06 -08:00
|
|
|
.filter(|item| item.kind == ty::AssocKind::Type)
|
|
|
|
.map(|item| item.def_id),
|
|
|
|
);
|
2018-12-16 00:00:46 +02:00
|
|
|
}
|
2022-11-24 18:14:58 -03:00
|
|
|
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
|
2020-10-16 14:04:11 -04:00
|
|
|
let pred = bound_predicate.rebind(pred);
|
2019-12-17 18:15:06 -08:00
|
|
|
// A `Self` within the original bound will be substituted with a
|
|
|
|
// `trait_object_dummy_self`, so check for that.
|
2022-09-05 14:03:53 +10:00
|
|
|
let references_self = match pred.skip_binder().term.unpack() {
|
|
|
|
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
|
|
|
ty::TermKind::Const(c) => {
|
|
|
|
c.ty().walk().any(|arg| arg == dummy_self.into())
|
|
|
|
}
|
2022-01-10 23:39:21 +00:00
|
|
|
};
|
2019-12-17 18:15:06 -08:00
|
|
|
|
|
|
|
// If the projection output contains `Self`, force the user to
|
|
|
|
// elaborate it explicitly to avoid a lot of complexity.
|
|
|
|
//
|
2022-03-30 15:14:15 -04:00
|
|
|
// The "classically useful" case is the following:
|
2019-12-17 18:15:06 -08:00
|
|
|
// ```
|
|
|
|
// trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
|
|
|
|
// type MyOutput;
|
|
|
|
// }
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// Here, the user could theoretically write `dyn MyTrait<Output = X>`,
|
|
|
|
// but actually supporting that would "expand" to an infinitely-long type
|
|
|
|
// `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
|
|
|
|
//
|
2019-12-18 11:12:50 -08:00
|
|
|
// Instead, we force the user to write
|
|
|
|
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
|
|
|
|
// the discussion in #56288 for alternatives.
|
2019-12-17 18:15:06 -08:00
|
|
|
if !references_self {
|
|
|
|
// Include projections defined on supertraits.
|
2022-12-26 04:19:27 +00:00
|
|
|
projection_bounds.push((pred, span));
|
2019-12-17 18:15:06 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
2018-11-06 23:17:11 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-05 10:54:38 +03:00
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
|
2022-12-26 04:19:27 +00:00
|
|
|
for (projection_bound, _) in &projection_bounds {
|
2020-03-01 20:56:30 +01:00
|
|
|
for def_ids in associated_types.values_mut() {
|
2019-12-17 18:15:06 -08:00
|
|
|
def_ids.remove(&projection_bound.projection_def_id());
|
|
|
|
}
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
|
|
|
|
2019-12-12 17:26:19 -08:00
|
|
|
self.complain_about_missing_associated_types(
|
|
|
|
associated_types,
|
|
|
|
potential_assoc_types,
|
2022-12-26 04:19:27 +00:00
|
|
|
hir_trait_bounds,
|
2019-12-12 17:26:19 -08:00
|
|
|
);
|
2015-03-16 18:45:01 +02:00
|
|
|
|
2019-04-29 03:58:24 +01:00
|
|
|
// De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
|
|
|
|
// `dyn Trait + Send`.
|
Avoid sorting predicates by `DefId`
Fixes issue #82920
Even if an item does not change between compilation sessions, it may end
up with a different `DefId`, since inserting/deleting an item affects
the `DefId`s of all subsequent items. Therefore, we use a `DefPathHash`
in the incremental compilation system, which is stable in the face of
changes to unrelated items.
In particular, the query system will consider the inputs to a query to
be unchanged if any `DefId`s in the inputs have their `DefPathHash`es
unchanged. Queries are pure functions, so the query result should be
unchanged if the query inputs are unchanged.
Unfortunately, it's possible to inadvertantly make a query result
incorrectly change across compilations, by relying on the specific value
of a `DefId`. Specifically, if the query result is a slice that gets
sorted by `DefId`, the precise order will depend on how the `DefId`s got
assigned in a particular compilation session. If some definitions end up
with different `DefId`s (but the same `DefPathHash`es) in a subsequent
compilation session, we will end up re-computing a *different* value for
the query, even though the query system expects the result to unchanged
due to the unchanged inputs.
It turns out that we have been sorting the predicates computed during
`astconv` by their `DefId`. These predicates make their way into the
`super_predicates_that_define_assoc_type`, which ends up getting used to
compute the vtables of trait objects. This, re-ordering these predicates
between compilation sessions can lead to undefined behavior at runtime -
the query system will re-use code built with a *differently ordered*
vtable, resulting in the wrong method being invoked at runtime.
This PR avoids sorting by `DefId` in `astconv`, fixing the
miscompilation. However, it's possible that other instances of this
issue exist - they could also be easily introduced in the future.
To fully fix this issue, we should
1. Turn on `-Z incremental-verify-ich` by default. This will cause the
compiler to ICE whenver an 'unchanged' query result changes between
compilation sessions, instead of causing a miscompilation.
2. Remove the `Ord` impls for `CrateNum` and `DefId`. This will make it
difficult to introduce ICEs in the first place.
2021-03-12 17:53:02 -05:00
|
|
|
// We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
|
|
|
|
// the bounds
|
|
|
|
let mut duplicates = FxHashSet::default();
|
|
|
|
auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
|
2019-04-29 03:58:24 +01:00
|
|
|
debug!("regular_traits: {:?}", regular_traits);
|
|
|
|
debug!("auto_traits: {:?}", auto_traits);
|
|
|
|
|
2019-04-03 11:46:40 +02:00
|
|
|
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
|
2021-02-12 22:32:46 +00:00
|
|
|
let existential_trait_refs = regular_traits.iter().map(|i| {
|
|
|
|
i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| {
|
2022-08-07 21:03:28 +02:00
|
|
|
assert_eq!(trait_ref.self_ty(), dummy_self);
|
|
|
|
|
2022-11-16 20:34:16 +00:00
|
|
|
// Verify that `dummy_self` did not leak inside default type parameters. This
|
2022-08-07 21:03:28 +02:00
|
|
|
// could not be done at path creation, since we need to see through trait aliases.
|
|
|
|
let mut missing_type_params = vec![];
|
2022-08-07 22:02:02 +02:00
|
|
|
let mut references_self = false;
|
2022-08-07 21:03:28 +02:00
|
|
|
let generics = tcx.generics_of(trait_ref.def_id);
|
|
|
|
let substs: Vec<_> = trait_ref
|
|
|
|
.substs
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.skip(1) // Remove `Self` for `ExistentialPredicate`.
|
|
|
|
.map(|(index, arg)| {
|
2022-08-17 20:22:52 +02:00
|
|
|
if arg == dummy_self.into() {
|
|
|
|
let param = &generics.params[index];
|
|
|
|
missing_type_params.push(param.name);
|
|
|
|
return tcx.ty_error().into();
|
|
|
|
} else if arg.walk().any(|arg| arg == dummy_self.into()) {
|
|
|
|
references_self = true;
|
|
|
|
return tcx.ty_error().into();
|
2022-08-07 21:03:28 +02:00
|
|
|
}
|
2022-08-13 18:39:30 +02:00
|
|
|
arg
|
2022-08-07 21:03:28 +02:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
let substs = tcx.intern_substs(&substs[..]);
|
|
|
|
|
|
|
|
let span = i.bottom().1;
|
2022-12-26 04:19:27 +00:00
|
|
|
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
|
2022-08-07 21:03:28 +02:00
|
|
|
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
|
|
|
|
&& hir_bound.span.contains(span)
|
|
|
|
});
|
|
|
|
self.complain_about_missing_type_params(
|
|
|
|
missing_type_params,
|
|
|
|
trait_ref.def_id,
|
|
|
|
span,
|
|
|
|
empty_generic_args,
|
|
|
|
);
|
|
|
|
|
2022-08-07 22:02:02 +02:00
|
|
|
if references_self {
|
|
|
|
let def_id = i.bottom().0.def_id();
|
|
|
|
let mut err = struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
i.bottom().1,
|
|
|
|
E0038,
|
|
|
|
"the {} `{}` cannot be made into an object",
|
|
|
|
tcx.def_kind(def_id).descr(def_id),
|
|
|
|
tcx.item_name(def_id),
|
|
|
|
);
|
|
|
|
err.note(
|
|
|
|
rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
|
|
|
|
.error_msg(),
|
2021-02-12 22:32:46 +00:00
|
|
|
);
|
2022-08-07 22:02:02 +02:00
|
|
|
err.emit();
|
2021-02-12 22:32:46 +00:00
|
|
|
}
|
2022-08-07 22:02:02 +02:00
|
|
|
|
2022-08-07 21:03:28 +02:00
|
|
|
ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
|
2021-02-12 22:32:46 +00:00
|
|
|
})
|
|
|
|
});
|
2022-08-07 21:03:28 +02:00
|
|
|
|
2022-12-26 04:19:27 +00:00
|
|
|
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
2022-08-13 18:39:30 +02:00
|
|
|
bound.map_bound(|mut b| {
|
|
|
|
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
|
|
|
|
|
|
|
// Like for trait refs, verify that `dummy_self` did not leak inside default type
|
|
|
|
// parameters.
|
|
|
|
let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
|
2022-08-17 20:22:52 +02:00
|
|
|
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
|
|
|
return true;
|
2022-08-13 18:39:30 +02:00
|
|
|
}
|
|
|
|
false
|
|
|
|
});
|
|
|
|
if references_self {
|
|
|
|
tcx.sess
|
|
|
|
.delay_span_bug(span, "trait object projection bounds reference `Self`");
|
|
|
|
let substs: Vec<_> = b
|
|
|
|
.projection_ty
|
|
|
|
.substs
|
|
|
|
.iter()
|
|
|
|
.map(|arg| {
|
2022-08-17 20:22:52 +02:00
|
|
|
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
2022-08-13 18:39:30 +02:00
|
|
|
return tcx.ty_error().into();
|
|
|
|
}
|
|
|
|
arg
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
b.projection_ty.substs = tcx.intern_substs(&substs[..]);
|
2018-11-01 19:43:38 +00:00
|
|
|
}
|
2022-08-13 18:39:30 +02:00
|
|
|
|
2021-02-12 22:32:46 +00:00
|
|
|
ty::ExistentialProjection::erase_self_ty(tcx, b)
|
2018-11-01 19:43:38 +00:00
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2020-12-30 04:19:09 +01:00
|
|
|
let regular_trait_predicates = existential_trait_refs
|
|
|
|
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
|
2020-12-11 15:02:46 -05:00
|
|
|
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
|
|
|
|
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
|
|
|
|
});
|
2021-05-15 15:19:01 -04:00
|
|
|
// N.b. principal, projections, auto traits
|
|
|
|
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut v = regular_trait_predicates
|
|
|
|
.chain(
|
2020-12-30 04:19:09 +01:00
|
|
|
existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
2021-05-15 15:19:01 -04:00
|
|
|
.chain(auto_trait_predicates)
|
2018-08-24 13:51:32 +10:00
|
|
|
.collect::<SmallVec<[_; 8]>>();
|
2020-12-11 15:02:46 -05:00
|
|
|
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
|
2018-12-04 15:17:35 +02:00
|
|
|
v.dedup();
|
2023-02-16 16:27:05 +11:00
|
|
|
let existential_predicates = tcx.intern_poly_existential_predicates(&v);
|
2016-11-16 09:21:49 -07:00
|
|
|
|
2018-11-01 03:08:04 +00:00
|
|
|
// Use explicitly-specified region bound.
|
2017-01-24 17:17:06 +02:00
|
|
|
let region_bound = if !lifetime.is_elided() {
|
|
|
|
self.ast_region_to_region(lifetime, None)
|
|
|
|
} else {
|
|
|
|
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
|
2023-02-06 18:38:52 +00:00
|
|
|
if tcx.named_bound_var(lifetime.hir_id).is_some() {
|
2017-01-25 17:32:44 +02:00
|
|
|
self.ast_region_to_region(lifetime, None)
|
|
|
|
} else {
|
2019-06-06 01:55:34 +01:00
|
|
|
self.re_infer(None, span).unwrap_or_else(|| {
|
2020-08-13 18:30:00 -07:00
|
|
|
let mut err = struct_span_err!(
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx.sess,
|
|
|
|
span,
|
|
|
|
E0228,
|
2019-03-26 17:34:32 +00:00
|
|
|
"the lifetime bound for this object type cannot be deduced \
|
2019-12-24 17:38:22 -05:00
|
|
|
from context; please supply an explicit bound"
|
2020-08-13 18:30:00 -07:00
|
|
|
);
|
2023-02-09 10:38:45 +00:00
|
|
|
let e = if borrowed {
|
2020-08-13 18:30:00 -07:00
|
|
|
// We will have already emitted an error E0106 complaining about a
|
|
|
|
// missing named lifetime in `&dyn Trait`, so we elide this one.
|
2023-02-09 10:38:45 +00:00
|
|
|
err.delay_as_bug()
|
2020-08-13 18:30:00 -07:00
|
|
|
} else {
|
2023-02-09 10:38:45 +00:00
|
|
|
err.emit()
|
|
|
|
};
|
2023-02-13 13:03:45 +11:00
|
|
|
tcx.mk_re_error(e)
|
2017-01-25 17:32:44 +02:00
|
|
|
})
|
|
|
|
}
|
2017-01-24 17:17:06 +02:00
|
|
|
})
|
2016-11-16 09:21:49 -07:00
|
|
|
};
|
|
|
|
debug!("region_bound: {:?}", region_bound);
|
|
|
|
|
2022-04-13 16:38:16 -07:00
|
|
|
let ty = tcx.mk_dynamic(existential_predicates, region_bound, representation);
|
2016-08-04 15:52:57 +03:00
|
|
|
debug!("trait_object_type: {:?}", ty);
|
|
|
|
ty
|
2015-03-16 18:45:01 +02:00
|
|
|
}
|
|
|
|
|
2019-04-17 10:24:50 -07:00
|
|
|
fn report_ambiguous_associated_type(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
2023-01-08 06:54:52 +00:00
|
|
|
types: &[String],
|
|
|
|
traits: &[String],
|
2020-04-19 13:00:18 +02:00
|
|
|
name: Symbol,
|
2022-01-22 18:49:12 -06:00
|
|
|
) -> ErrorGuaranteed {
|
2019-04-17 10:24:50 -07:00
|
|
|
let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
|
2022-06-07 13:39:21 -07:00
|
|
|
if self
|
|
|
|
.tcx()
|
|
|
|
.resolutions(())
|
|
|
|
.confused_type_with_std_module
|
|
|
|
.keys()
|
|
|
|
.any(|full_span| full_span.contains(span))
|
|
|
|
{
|
2023-01-08 06:54:52 +00:00
|
|
|
err.span_suggestion_verbose(
|
2022-06-07 13:39:21 -07:00
|
|
|
span.shrink_to_lo(),
|
2019-04-17 10:24:50 -07:00
|
|
|
"you are looking for the module in `std`, not the primitive type",
|
2022-06-13 15:48:40 +09:00
|
|
|
"std::",
|
2019-04-17 10:24:50 -07:00
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
} else {
|
2023-01-08 06:54:52 +00:00
|
|
|
match (types, traits) {
|
|
|
|
([], []) => {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span,
|
|
|
|
&format!(
|
|
|
|
"if there were a type named `Type` that implements a trait named \
|
|
|
|
`Trait` with associated type `{name}`, you could use the \
|
|
|
|
fully-qualified path",
|
|
|
|
),
|
|
|
|
format!("<Type as Trait>::{name}"),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
([], [trait_str]) => {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span,
|
|
|
|
&format!(
|
|
|
|
"if there were a type named `Example` that implemented `{trait_str}`, \
|
|
|
|
you could use the fully-qualified path",
|
|
|
|
),
|
|
|
|
format!("<Example as {trait_str}>::{name}"),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
([], traits) => {
|
|
|
|
err.span_suggestions(
|
|
|
|
span,
|
|
|
|
&format!(
|
|
|
|
"if there were a type named `Example` that implemented one of the \
|
|
|
|
traits with associated type `{name}`, you could use the \
|
|
|
|
fully-qualified path",
|
|
|
|
),
|
|
|
|
traits
|
|
|
|
.iter()
|
|
|
|
.map(|trait_str| format!("<Example as {trait_str}>::{name}"))
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
([type_str], []) => {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span,
|
|
|
|
&format!(
|
|
|
|
"if there were a trait named `Example` with associated type `{name}` \
|
|
|
|
implemented for `{type_str}`, you could use the fully-qualified path",
|
|
|
|
),
|
|
|
|
format!("<{type_str} as Example>::{name}"),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
(types, []) => {
|
|
|
|
err.span_suggestions(
|
|
|
|
span,
|
|
|
|
&format!(
|
|
|
|
"if there were a trait named `Example` with associated type `{name}` \
|
|
|
|
implemented for one of the types, you could use the fully-qualified \
|
|
|
|
path",
|
|
|
|
),
|
|
|
|
types
|
|
|
|
.into_iter()
|
|
|
|
.map(|type_str| format!("<{type_str} as Example>::{name}")),
|
|
|
|
Applicability::HasPlaceholders,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
(types, traits) => {
|
|
|
|
let mut suggestions = vec![];
|
|
|
|
for type_str in types {
|
|
|
|
for trait_str in traits {
|
|
|
|
suggestions.push(format!("<{type_str} as {trait_str}>::{name}"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err.span_suggestions(
|
|
|
|
span,
|
|
|
|
"use the fully-qualified path",
|
|
|
|
suggestions,
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 10:24:50 -07:00
|
|
|
}
|
2022-01-22 18:49:12 -06:00
|
|
|
err.emit()
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-03-16 18:45:01 +02:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
// Search for a bound on a type parameter which includes the associated item
|
2019-05-20 16:19:34 +01:00
|
|
|
// given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
|
2017-02-11 19:26:13 +02:00
|
|
|
// This function will fail if there are no suitable bounds or there is
|
2016-05-11 08:48:12 +03:00
|
|
|
// any ambiguity.
|
2019-12-24 17:38:22 -05:00
|
|
|
fn find_bound_for_assoc_item(
|
|
|
|
&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> {
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
2015-02-26 19:15:57 +01:00
|
|
|
|
2019-07-12 06:31:42 -04:00
|
|
|
debug!(
|
|
|
|
"find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
|
2019-12-24 17:38:22 -05:00
|
|
|
ty_param_def_id, assoc_name, span,
|
2019-07-12 06:31:42 -04:00
|
|
|
);
|
|
|
|
|
2020-12-03 20:10:55 -03:00
|
|
|
let predicates = &self
|
|
|
|
.get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
|
|
|
|
.predicates;
|
2019-07-12 06:31:42 -04:00
|
|
|
|
|
|
|
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
|
|
|
|
|
2022-04-08 23:06:20 +02:00
|
|
|
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
|
2019-12-18 20:35:18 +01:00
|
|
|
self.one_bound_for_assoc_type(
|
2019-12-24 17:38:22 -05:00
|
|
|
|| {
|
2020-12-03 20:10:55 -03:00
|
|
|
traits::transitive_bounds_that_define_assoc_type(
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx,
|
2020-11-22 02:13:53 +01:00
|
|
|
predicates.iter().filter_map(|(p, _)| {
|
2021-12-12 12:34:46 +08:00
|
|
|
Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
|
2020-11-22 02:13:53 +01:00
|
|
|
}),
|
2020-12-03 20:10:55 -03:00
|
|
|
assoc_name,
|
2019-12-24 17:38:22 -05:00
|
|
|
)
|
|
|
|
},
|
2020-01-02 00:19:29 +01:00
|
|
|
|| param_name.to_string(),
|
2019-12-18 20:35:18 +01:00
|
|
|
assoc_name,
|
|
|
|
span,
|
2020-01-02 00:19:29 +01: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
|
|
|
|
2019-12-12 21:15:19 -08:00
|
|
|
// Checks that `bounds` contains exactly one element and reports appropriate
|
|
|
|
// errors otherwise.
|
2022-10-20 09:39:09 +00:00
|
|
|
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)]
|
2019-12-24 17:38:22 -05:00
|
|
|
fn one_bound_for_assoc_type<I>(
|
|
|
|
&self,
|
|
|
|
all_candidates: impl Fn() -> I,
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name: impl Fn() -> String,
|
2020-04-19 13:00:18 +02:00
|
|
|
assoc_name: Ident,
|
2019-12-24 17:38:22 -05:00
|
|
|
span: Span,
|
2020-01-02 00:19:29 +01:00
|
|
|
is_equality: impl Fn() -> Option<String>,
|
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
|
|
|
{
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut matching_candidates = all_candidates()
|
2022-02-02 16:42:37 +00:00
|
|
|
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
|
|
|
|
let mut const_candidates = all_candidates()
|
|
|
|
.filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
|
|
|
|
|
|
|
|
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
|
|
|
|
(Some(bound), _) => (bound, matching_candidates.next()),
|
|
|
|
(None, Some(bound)) => (bound, const_candidates.next()),
|
|
|
|
(None, None) => {
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = self.complain_about_assoc_type_not_found(
|
2019-12-18 20:35:18 +01:00
|
|
|
all_candidates,
|
2020-01-02 00:19:29 +01:00
|
|
|
&ty_param_name(),
|
2019-12-18 20:35:18 +01:00
|
|
|
assoc_name,
|
2019-12-24 17:38:22 -05:00
|
|
|
span,
|
2019-12-18 20:35:18 +01:00
|
|
|
);
|
2022-01-22 18:49:12 -06: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
|
|
|
|
2022-02-02 16:42:37 +00:00
|
|
|
if let Some(bound2) = next_cand {
|
2022-10-20 09:39:09 +00:00
|
|
|
debug!(?bound2);
|
2019-07-12 06:31:42 -04:00
|
|
|
|
2020-01-02 00:19:29 +01:00
|
|
|
let is_equality = is_equality();
|
2021-09-03 12:36:33 +02:00
|
|
|
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
|
2019-12-12 21:15:19 -08:00
|
|
|
let mut err = if is_equality.is_some() {
|
|
|
|
// More specific Error Index entry.
|
|
|
|
struct_span_err!(
|
|
|
|
self.tcx().sess,
|
|
|
|
span,
|
|
|
|
E0222,
|
|
|
|
"ambiguous associated type `{}` in bounds of `{}`",
|
|
|
|
assoc_name,
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name()
|
2019-12-12 21:15:19 -08:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
struct_span_err!(
|
|
|
|
self.tcx().sess,
|
|
|
|
span,
|
|
|
|
E0221,
|
|
|
|
"ambiguous associated type `{}` in bounds of `{}`",
|
|
|
|
assoc_name,
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name()
|
2019-12-12 21:15:19 -08:00
|
|
|
)
|
|
|
|
};
|
2017-05-04 14:17:23 +02:00
|
|
|
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-12-12 21:15:19 -08:00
|
|
|
let mut where_bounds = vec![];
|
2016-11-27 06:54:50 -07:00
|
|
|
for bound in bounds {
|
2020-02-17 13:09:01 -08:00
|
|
|
let bound_id = bound.def_id();
|
2019-12-24 17:38:22 -05:00
|
|
|
let bound_span = self
|
|
|
|
.tcx()
|
2020-02-17 13:09:01 -08:00
|
|
|
.associated_items(bound_id)
|
|
|
|
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
|
2019-06-17 23:40:24 +01:00
|
|
|
.and_then(|item| self.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,
|
2019-12-24 17:38:22 -05:00
|
|
|
format!(
|
|
|
|
"ambiguous `{}` from `{}`",
|
|
|
|
assoc_name,
|
2019-12-12 14:48:46 -08:00
|
|
|
bound.print_only_trait_path(),
|
2019-12-24 17:38:22 -05:00
|
|
|
),
|
|
|
|
);
|
2019-12-12 21:15:19 -08:00
|
|
|
if let Some(constraint) = &is_equality {
|
|
|
|
where_bounds.push(format!(
|
|
|
|
" T: {trait}::{assoc} = {constraint}",
|
|
|
|
trait=bound.print_only_trait_path(),
|
|
|
|
assoc=assoc_name,
|
|
|
|
constraint=constraint,
|
|
|
|
));
|
|
|
|
} else {
|
2021-08-10 10:53:43 +00:00
|
|
|
err.span_suggestion_verbose(
|
|
|
|
span.with_hi(assoc_name.span.lo()),
|
2019-12-12 21:15:19 -08:00
|
|
|
"use fully qualified syntax to disambiguate",
|
|
|
|
format!(
|
2021-08-10 10:53:43 +00:00
|
|
|
"<{} as {}>::",
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name(),
|
2019-12-12 21:15:19 -08:00
|
|
|
bound.print_only_trait_path(),
|
|
|
|
),
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
2019-12-12 14:48:46 -08:00
|
|
|
} else {
|
|
|
|
err.note(&format!(
|
2019-12-24 17:38:22 -05:00
|
|
|
"associated type `{}` could derive from `{}`",
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name(),
|
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() {
|
|
|
|
err.help(&format!(
|
|
|
|
"consider introducing a new type parameter `T` and adding `where` constraints:\
|
|
|
|
\n where\n T: {},\n{}",
|
2020-01-02 00:19:29 +01:00
|
|
|
ty_param_name(),
|
2019-12-12 21:15:19 -08:00
|
|
|
where_bounds.join(",\n"),
|
|
|
|
));
|
|
|
|
}
|
2022-01-22 18:49:12 -06:00
|
|
|
let reported = err.emit();
|
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
|
|
|
|
2022-09-17 21:35:47 +03:00
|
|
|
// Create a type from a path to an associated type or to an enum variant.
|
2019-01-10 23:23:30 +03:00
|
|
|
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
|
2018-11-01 19:43:38 +00:00
|
|
|
// and item_segment is the path segment for `D`. We return a type and a def for
|
2016-05-11 08:48:12 +03:00
|
|
|
// the whole path.
|
2019-01-10 23:23:30 +03:00
|
|
|
// Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
|
2018-11-01 19:43:38 +00:00
|
|
|
// parameter or `Self`.
|
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.
|
2022-10-20 09:39:09 +00:00
|
|
|
#[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)]
|
2019-01-10 23:23:30 +03:00
|
|
|
pub fn associated_path_to_ty(
|
|
|
|
&self,
|
2019-02-18 10:59:17 +01:00
|
|
|
hir_ref_id: hir::HirId,
|
2019-01-10 23:23:30 +03:00
|
|
|
span: Span,
|
|
|
|
qself_ty: Ty<'tcx>,
|
2022-05-27 19:53:31 -07:00
|
|
|
qself: &hir::Ty<'_>,
|
2019-12-01 16:08:58 +01:00
|
|
|
assoc_segment: &hir::PathSegment<'_>,
|
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> {
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
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
|
|
|
|
2019-01-10 23:23:30 +03:00
|
|
|
// Check if we have an enum variant.
|
|
|
|
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);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(slice::from_ref(assoc_segment).iter(), |err| {
|
|
|
|
err.note("enum variants can't have type parameters");
|
2022-05-31 12:53:52 -07:00
|
|
|
let type_name = tcx.item_name(adt_def.did());
|
|
|
|
let msg = format!(
|
|
|
|
"you might have meant to specity type parameters on enum \
|
|
|
|
`{type_name}`"
|
|
|
|
);
|
2022-05-27 19:53:31 -07:00
|
|
|
let Some(args) = assoc_segment.args else { return; };
|
2022-05-31 12:53:52 -07:00
|
|
|
// Get the span of the generics args *including* the leading `::`.
|
2022-05-27 19:53:31 -07:00
|
|
|
let args_span = assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
|
2022-05-31 12:53:52 -07:00
|
|
|
if tcx.generics_of(adt_def.did()).count() == 0 {
|
|
|
|
// FIXME(estebank): we could also verify that the arguments being
|
|
|
|
// work for the `enum`, instead of just looking if it takes *any*.
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
args_span,
|
2022-06-02 14:06:54 -07:00
|
|
|
&format!("{type_name} doesn't have generic parameters"),
|
2022-06-13 15:48:40 +09:00
|
|
|
"",
|
2022-05-31 12:53:52 -07:00
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2022-05-27 19:53:31 -07:00
|
|
|
let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
|
|
|
|
err.note(&msg);
|
|
|
|
return;
|
|
|
|
};
|
2022-05-31 12:53:52 -07:00
|
|
|
let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::QPath::Resolved(_, path)
|
|
|
|
) = &qself.kind {
|
2022-05-27 19:53:31 -07:00
|
|
|
// If the path segment already has type params, we want to overwrite
|
|
|
|
// them.
|
2023-02-16 00:06:51 +01:00
|
|
|
match &path.segments {
|
2022-05-31 12:53:52 -07:00
|
|
|
// `segment` is the previous to last element on the path,
|
|
|
|
// which would normally be the `enum` itself, while the last
|
|
|
|
// `_` `PathSegment` corresponds to the variant.
|
|
|
|
[.., hir::PathSegment {
|
|
|
|
ident,
|
|
|
|
args,
|
2022-08-30 15:10:28 +10:00
|
|
|
res: Res::Def(DefKind::Enum, _),
|
2022-05-31 12:53:52 -07:00
|
|
|
..
|
|
|
|
}, _] => (
|
|
|
|
// We need to include the `::` in `Type::Variant::<Args>`
|
|
|
|
// to point the span to `::<Args>`, not just `<Args>`.
|
|
|
|
ident.span.shrink_to_hi().to(args.map_or(
|
|
|
|
ident.span.shrink_to_hi(),
|
2022-05-27 19:53:31 -07:00
|
|
|
|a| a.span_ext)),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
[segment] => (
|
2022-05-31 12:53:52 -07:00
|
|
|
// We need to include the `::` in `Type::Variant::<Args>`
|
|
|
|
// to point the span to `::<Args>`, not just `<Args>`.
|
2022-05-27 19:53:31 -07:00
|
|
|
segment.ident.span.shrink_to_hi().to(segment.args.map_or(
|
|
|
|
segment.ident.span.shrink_to_hi(),
|
|
|
|
|a| a.span_ext)),
|
|
|
|
kw::SelfUpper == segment.ident.name,
|
|
|
|
),
|
2022-05-31 12:53:52 -07:00
|
|
|
_ => {
|
|
|
|
err.note(&msg);
|
|
|
|
return;
|
|
|
|
}
|
2022-05-27 19:53:31 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err.note(&msg);
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
let suggestion = vec![
|
|
|
|
if is_self {
|
|
|
|
// Account for people writing `Self::Variant::<Args>`, where
|
2022-05-31 12:53:52 -07:00
|
|
|
// `Self` is the enum, and suggest replacing `Self` with the
|
|
|
|
// appropriate type: `Type::<Args>::Variant`.
|
2022-05-27 19:53:31 -07:00
|
|
|
(qself.span, format!("{type_name}{snippet}"))
|
|
|
|
} else {
|
|
|
|
(qself_sugg_span, snippet)
|
|
|
|
},
|
|
|
|
(args_span, String::new()),
|
|
|
|
];
|
2022-05-31 12:53:52 -07:00
|
|
|
err.multipart_suggestion_verbose(
|
|
|
|
&msg,
|
|
|
|
suggestion,
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
2022-05-27 19:53:31 -07:00
|
|
|
});
|
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
|
|
|
}
|
|
|
|
|
2022-12-08 13:31:21 +01:00
|
|
|
if let Some((ty, did)) = self.lookup_inherent_assoc_ty(
|
|
|
|
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.
|
2022-01-22 18:49:12 -06:00
|
|
|
let guar = tcx.sess.delay_span_bug(span, "expected cycle error");
|
|
|
|
return Err(guar);
|
2017-02-19 00:15:30 +03:00
|
|
|
};
|
2017-02-14 11:32:00 +02:00
|
|
|
|
2019-12-18 20:35:18 +01:00
|
|
|
self.one_bound_for_assoc_type(
|
2023-01-11 11:32:33 -07:00
|
|
|
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
|
2020-01-02 00:19:29 +01:00
|
|
|
|| "Self".to_string(),
|
2019-12-18 20:35:18 +01:00
|
|
|
assoc_ident,
|
2019-12-24 17:38:22 -05:00
|
|
|
span,
|
2020-01-02 00:19:29 +01: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),
|
2020-04-12 13:45:41 +01:00
|
|
|
) => self.find_bound_for_assoc_item(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
|
|
|
|
let msg = format!("expected type, found variant `{}`", assoc_ident);
|
2022-01-22 18:49:12 -06:00
|
|
|
tcx.sess.span_err(span, &msg)
|
2019-01-10 23:23:30 +03:00
|
|
|
} else if qself_ty.is_enum() {
|
2020-01-08 08:05:31 -08:00
|
|
|
let mut err = struct_span_err!(
|
|
|
|
tcx.sess,
|
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,
|
|
|
|
format!("variant not found in `{}`", qself_ty),
|
|
|
|
);
|
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()) {
|
|
|
|
err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
|
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.
|
|
|
|
struct_span_err!(
|
|
|
|
tcx.sess,
|
|
|
|
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 {
|
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
|
|
|
|
2019-01-10 23:23:30 +03:00
|
|
|
// Don't print `TyErr` to the user.
|
2019-04-17 10:24:50 -07:00
|
|
|
self.report_ambiguous_associated_type(
|
|
|
|
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
|
|
|
)
|
|
|
|
};
|
|
|
|
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();
|
2022-11-13 05:12:44 +01:00
|
|
|
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) else {
|
|
|
|
// Assume that if it's not matched, there must be a const defined with the same name
|
|
|
|
// but it was used in a type position.
|
2022-02-02 16:42:37 +00:00
|
|
|
let msg = format!("found associated const `{assoc_ident}` when type was expected");
|
2022-01-22 18:49:12 -06:00
|
|
|
let guar = tcx.sess.struct_span_err(span, &msg).emit();
|
|
|
|
return Err(guar);
|
2022-02-02 16:42:37 +00:00
|
|
|
};
|
2017-07-11 10:33:09 -04:00
|
|
|
|
2022-11-13 05:12:44 +01:00
|
|
|
let ty = self.projected_ty_from_poly_trait_ref(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 {
|
2022-09-16 11:01:02 +04:00
|
|
|
tcx.struct_span_lint_hir(
|
|
|
|
AMBIGUOUS_ASSOCIATED_ITEMS,
|
|
|
|
hir_ref_id,
|
|
|
|
span,
|
|
|
|
"ambiguous associated item",
|
|
|
|
|lint| {
|
|
|
|
let mut could_refer_to = |kind: DefKind, def_id, also| {
|
|
|
|
let note_msg = format!(
|
|
|
|
"`{}` could{} refer to the {} defined here",
|
|
|
|
assoc_ident,
|
|
|
|
also,
|
|
|
|
kind.descr(def_id)
|
|
|
|
);
|
|
|
|
lint.span_note(tcx.def_span(def_id), ¬e_msg);
|
|
|
|
};
|
2019-01-10 23:23:30 +03:00
|
|
|
|
2022-09-16 11:01:02 +04:00
|
|
|
could_refer_to(DefKind::Variant, variant_def_id, "");
|
2022-11-13 05:12:44 +01:00
|
|
|
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
|
2020-01-31 22:24:57 +10:00
|
|
|
|
2022-09-16 11:01:02 +04: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-09-16 11:01:02 +04:00
|
|
|
lint
|
|
|
|
},
|
|
|
|
);
|
2019-01-10 23:23:30 +03:00
|
|
|
}
|
2022-11-13 05:12:44 +01:00
|
|
|
Ok((ty, DefKind::AssocTy, assoc_ty_did))
|
|
|
|
}
|
|
|
|
|
2022-12-08 13:31:21 +01:00
|
|
|
fn lookup_inherent_assoc_ty(
|
|
|
|
&self,
|
|
|
|
name: Ident,
|
|
|
|
segment: &hir::PathSegment<'_>,
|
|
|
|
adt_did: DefId,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
block: hir::HirId,
|
|
|
|
span: Span,
|
|
|
|
) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
let candidates: Vec<_> = tcx
|
|
|
|
.inherent_impls(adt_did)
|
|
|
|
.iter()
|
|
|
|
.filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?)))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
if candidates.is_empty() {
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
|
|
|
|
let cause = ObligationCause::misc(span, block.owner.def_id);
|
|
|
|
let mut unsatisfied_predicates = Vec::new();
|
|
|
|
|
|
|
|
for &(impl_, (assoc_item, def_scope)) in &candidates {
|
|
|
|
let infcx = tcx.infer_ctxt().ignoring_regions().build();
|
|
|
|
let param_env = tcx.param_env(impl_);
|
|
|
|
|
|
|
|
let impl_ty = tcx.type_of(impl_);
|
|
|
|
let impl_substs = self.fresh_item_substs(impl_, &infcx);
|
|
|
|
let impl_ty = impl_ty.subst(tcx, impl_substs);
|
|
|
|
|
|
|
|
let InferOk { value: impl_ty, obligations } =
|
|
|
|
infcx.at(&cause, param_env).normalize(impl_ty);
|
|
|
|
|
|
|
|
// Check that the Self-types can be related.
|
|
|
|
let Ok(InferOk { obligations: sub_obligations, value: () }) = infcx
|
|
|
|
.at(&ObligationCause::dummy(), param_env)
|
|
|
|
.define_opaque_types(false)
|
|
|
|
.sup(impl_ty, self_ty)
|
|
|
|
else {
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Check whether the impl imposes obligations we have to worry about.
|
|
|
|
let impl_bounds = tcx.predicates_of(impl_);
|
|
|
|
let impl_bounds = impl_bounds.instantiate(tcx, impl_substs);
|
|
|
|
|
|
|
|
let InferOk { value: impl_bounds, obligations: norm_obligations } =
|
|
|
|
infcx.at(&cause, param_env).normalize(impl_bounds);
|
|
|
|
|
|
|
|
let impl_obligations =
|
|
|
|
traits::predicates_for_generics(|_, _| cause.clone(), param_env, impl_bounds);
|
|
|
|
|
|
|
|
let candidate_obligations = impl_obligations
|
|
|
|
.chain(norm_obligations.into_iter())
|
|
|
|
.chain(obligations.iter().cloned());
|
|
|
|
|
|
|
|
let mut matches = true;
|
|
|
|
|
|
|
|
// Evaluate those obligations to see if they might possibly hold.
|
|
|
|
for o in candidate_obligations {
|
|
|
|
let o = infcx.resolve_vars_if_possible(o);
|
|
|
|
if !infcx.predicate_may_hold(&o) {
|
|
|
|
matches = false;
|
|
|
|
unsatisfied_predicates.push(o.predicate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evaluate those obligations to see if they might possibly hold.
|
|
|
|
for o in sub_obligations {
|
|
|
|
let o = infcx.resolve_vars_if_possible(o);
|
|
|
|
if !infcx.predicate_may_hold(&o) {
|
|
|
|
matches = false;
|
|
|
|
unsatisfied_predicates.push(o.predicate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !matches {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
|
|
|
|
|
|
|
|
let ty::Adt(_, adt_substs) = self_ty.kind() else {
|
|
|
|
bug!("unreachable: `lookup_inherent_assoc_ty` is only called on ADTs");
|
|
|
|
};
|
|
|
|
|
|
|
|
let item_substs =
|
|
|
|
self.create_substs_for_associated_item(span, assoc_item, segment, adt_substs);
|
|
|
|
// FIXME(inherent_associated_types): Check if the obligations arising from the
|
|
|
|
// where-clause & the bounds on the associated type and its parameters hold.
|
|
|
|
let ty = tcx.type_of(assoc_item).subst(tcx, item_substs);
|
|
|
|
return Ok(Some((ty, assoc_item)));
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(self.complain_about_inherent_assoc_type_not_found(
|
|
|
|
name,
|
|
|
|
self_ty,
|
|
|
|
&candidates.into_iter().map(|(impl_, _)| impl_).collect::<Vec<_>>(),
|
|
|
|
unsatisfied_predicates,
|
|
|
|
span,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME(fmease): Copied from `rustc_hir_typeck::method::probe`. Deduplicate.
|
|
|
|
fn fresh_item_substs(&self, def_id: DefId, infcx: &InferCtxt<'tcx>) -> SubstsRef<'tcx> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
|
|
|
GenericParamDefKind::Type { .. } => infcx
|
|
|
|
.next_ty_var(TypeVariableOrigin {
|
|
|
|
kind: TypeVariableOriginKind::SubstitutionPlaceholder,
|
|
|
|
span: tcx.def_span(def_id),
|
|
|
|
})
|
|
|
|
.into(),
|
|
|
|
GenericParamDefKind::Const { .. } => {
|
|
|
|
let span = tcx.def_span(def_id);
|
|
|
|
let origin = ConstVariableOrigin {
|
|
|
|
kind: ConstVariableOriginKind::SubstitutionPlaceholder,
|
|
|
|
span,
|
|
|
|
};
|
|
|
|
infcx
|
|
|
|
.next_const_var(
|
|
|
|
tcx.type_of(param.def_id)
|
|
|
|
.no_bound_vars()
|
|
|
|
.expect("const parameter types cannot be generic"),
|
|
|
|
origin,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lookup_assoc_ty(
|
|
|
|
&self,
|
|
|
|
name: Ident,
|
|
|
|
block: hir::HirId,
|
|
|
|
span: Span,
|
|
|
|
scope: DefId,
|
|
|
|
) -> Option<DefId> {
|
|
|
|
let (item, def_scope) = self.lookup_assoc_ty_unchecked(name, block, scope)?;
|
|
|
|
self.check_assoc_ty(item, name, def_scope, block, span);
|
|
|
|
Some(item)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lookup_assoc_ty_unchecked(
|
|
|
|
&self,
|
|
|
|
name: Ident,
|
|
|
|
block: hir::HirId,
|
|
|
|
scope: DefId,
|
|
|
|
) -> Option<(DefId, DefId)> {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block);
|
|
|
|
|
|
|
|
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
|
|
|
|
// of calling `find_by_name_and_kind`.
|
|
|
|
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))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_assoc_ty(
|
|
|
|
&self,
|
|
|
|
item: DefId,
|
|
|
|
name: Ident,
|
|
|
|
def_scope: DefId,
|
|
|
|
block: hir::HirId,
|
|
|
|
span: Span,
|
|
|
|
) {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
let kind = DefKind::AssocTy;
|
|
|
|
|
|
|
|
if !tcx.visibility(item).is_accessible_from(def_scope, tcx) {
|
|
|
|
let kind = kind.descr(item);
|
|
|
|
let msg = format!("{kind} `{name}` is private");
|
|
|
|
let def_span = tcx.def_span(item);
|
|
|
|
tcx.sess
|
|
|
|
.struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
|
|
|
|
.span_label(span, &format!("private {kind}"))
|
|
|
|
.span_label(def_span, &format!("{kind} defined here"))
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
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 {
|
|
|
|
assert!(!qself_ty.needs_infer());
|
|
|
|
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| {
|
|
|
|
let trait_ref = tcx.impl_trait_ref(impl_def_id);
|
|
|
|
trait_ref.map_or(false, |trait_ref| {
|
|
|
|
let impl_ = trait_ref.subst(
|
|
|
|
tcx,
|
|
|
|
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
|
|
|
|
);
|
|
|
|
infcx
|
|
|
|
.can_eq(
|
|
|
|
ty::ParamEnv::empty(),
|
|
|
|
tcx.erase_regions(impl_.self_ty()),
|
|
|
|
tcx.erase_regions(qself_ty),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
fn qpath_to_ty(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
opt_self_ty: Option<Ty<'tcx>>,
|
|
|
|
item_def_id: DefId,
|
2019-12-01 16:08:58 +01:00
|
|
|
trait_segment: &hir::PathSegment<'_>,
|
|
|
|
item_segment: &hir::PathSegment<'_>,
|
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);
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2019-11-01 13:50:36 +01:00
|
|
|
debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
|
|
|
|
|
2022-10-31 16:19:36 +00:00
|
|
|
let parent_def_id = def_id.as_local().map(|def_id| tcx.hir().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());
|
2019-11-02 09:49:05 +01:00
|
|
|
|
|
|
|
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
|
|
|
|
|
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)
|
|
|
|
.filter(|impl_def_id| {
|
|
|
|
// Consider only accessible traits
|
|
|
|
tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx)
|
|
|
|
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
|
|
|
|
})
|
|
|
|
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
|
2023-01-10 14:57:22 -07:00
|
|
|
.map(|impl_| impl_.subst_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`
|
2022-11-03 14:15:17 +08:00
|
|
|
let reported = self.report_ambiguous_associated_type(
|
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
|
|
|
);
|
2022-11-03 14:15:17 +08:00
|
|
|
return tcx.ty_error_with_guaranteed(reported)
|
2016-05-11 08:48:12 +03:00
|
|
|
};
|
2014-11-08 06:59:10 -05:00
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
debug!("qpath_to_ty: self_type={:?}", self_ty);
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2022-10-20 09:39:09 +00:00
|
|
|
let trait_ref = self.ast_path_to_mono_trait_ref(
|
|
|
|
span,
|
|
|
|
trait_def_id,
|
|
|
|
self_ty,
|
|
|
|
trait_segment,
|
|
|
|
false,
|
2022-11-04 16:28:01 +00:00
|
|
|
constness,
|
2022-10-20 09:39:09 +00:00
|
|
|
);
|
2014-11-08 06:59:10 -05:00
|
|
|
|
2019-12-08 17:04:17 +00:00
|
|
|
let item_substs = self.create_substs_for_associated_item(
|
|
|
|
span,
|
|
|
|
item_def_id,
|
|
|
|
item_segment,
|
|
|
|
trait_ref.substs,
|
|
|
|
);
|
|
|
|
|
2016-05-11 08:48:12 +03:00
|
|
|
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
|
2014-11-08 06:59:10 -05:00
|
|
|
|
2022-09-17 21:35:47 +03:00
|
|
|
tcx.mk_projection(item_def_id, item_substs)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2022-05-27 19:53:31 -07:00
|
|
|
pub fn prohibit_generics<'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,
|
2022-08-10 03:39:41 +00:00
|
|
|
extend: impl Fn(&mut Diagnostic),
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> bool {
|
2022-05-27 15:20:21 -07:00
|
|
|
let args = segments.clone().flat_map(|segment| segment.args().args);
|
2022-06-20 20:42:58 +03:00
|
|
|
|
|
|
|
let (lt, ty, ct, inf) =
|
|
|
|
args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg {
|
|
|
|
hir::GenericArg::Lifetime(_) => (true, ty, ct, inf),
|
|
|
|
hir::GenericArg::Type(_) => (lt, true, ct, inf),
|
|
|
|
hir::GenericArg::Const(_) => (lt, ty, true, inf),
|
|
|
|
hir::GenericArg::Infer(_) => (lt, ty, ct, true),
|
|
|
|
});
|
|
|
|
let mut emitted = false;
|
|
|
|
if lt || ty || ct || inf {
|
|
|
|
let types_and_spans: Vec<_> = segments
|
|
|
|
.clone()
|
|
|
|
.flat_map(|segment| {
|
2022-08-30 15:10:28 +10:00
|
|
|
if segment.args().args.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some((
|
|
|
|
match segment.res {
|
|
|
|
Res::PrimTy(ty) => format!("{} `{}`", segment.res.descr(), ty.name()),
|
2022-06-02 14:06:54 -07:00
|
|
|
Res::Def(_, def_id)
|
|
|
|
if let Some(name) = self.tcx().opt_item_name(def_id) => {
|
2022-08-30 15:10:28 +10:00
|
|
|
format!("{} `{name}`", segment.res.descr())
|
2022-06-02 14:06:54 -07:00
|
|
|
}
|
|
|
|
Res::Err => "this type".to_string(),
|
2022-08-30 15:10:28 +10:00
|
|
|
_ => segment.res.descr().to_string(),
|
2022-06-01 16:55:30 -07:00
|
|
|
},
|
|
|
|
segment.ident.span,
|
|
|
|
))
|
2022-08-30 15:10:28 +10:00
|
|
|
}
|
2022-06-01 16:55:30 -07:00
|
|
|
})
|
2022-06-20 20:42:58 +03:00
|
|
|
.collect();
|
|
|
|
let this_type = match &types_and_spans[..] {
|
|
|
|
[.., _, (last, _)] => format!(
|
|
|
|
"{} and {last}",
|
|
|
|
types_and_spans[..types_and_spans.len() - 1]
|
|
|
|
.iter()
|
|
|
|
.map(|(x, _)| x.as_str())
|
|
|
|
.intersperse(&", ")
|
|
|
|
.collect::<String>()
|
|
|
|
),
|
|
|
|
[(only, _)] => only.to_string(),
|
|
|
|
[] => "this type".to_string(),
|
|
|
|
};
|
2022-05-27 15:20:21 -07:00
|
|
|
|
2022-06-02 14:06:54 -07:00
|
|
|
let arg_spans: Vec<Span> = args.map(|arg| arg.span()).collect();
|
2022-05-27 15:20:21 -07:00
|
|
|
|
2022-06-02 14:06:54 -07:00
|
|
|
let mut kinds = Vec::with_capacity(4);
|
2022-05-27 15:20:21 -07:00
|
|
|
if lt {
|
2022-06-02 14:06:54 -07:00
|
|
|
kinds.push("lifetime");
|
2019-06-12 11:42:58 +03:00
|
|
|
}
|
2022-05-27 15:20:21 -07:00
|
|
|
if ty {
|
2022-06-02 14:06:54 -07:00
|
|
|
kinds.push("type");
|
2022-05-27 15:20:21 -07:00
|
|
|
}
|
|
|
|
if ct {
|
2022-06-02 14:06:54 -07:00
|
|
|
kinds.push("const");
|
2022-05-27 15:20:21 -07:00
|
|
|
}
|
|
|
|
if inf {
|
2022-06-02 14:06:54 -07:00
|
|
|
kinds.push("generic");
|
2022-05-27 15:20:21 -07:00
|
|
|
}
|
2022-06-02 14:06:54 -07:00
|
|
|
let (kind, s) = match kinds[..] {
|
2022-05-27 15:20:21 -07:00
|
|
|
[.., _, last] => (
|
|
|
|
format!(
|
2022-06-01 16:55:30 -07:00
|
|
|
"{} and {last}",
|
2022-06-02 14:06:54 -07:00
|
|
|
kinds[..kinds.len() - 1]
|
2022-05-27 15:20:21 -07:00
|
|
|
.iter()
|
|
|
|
.map(|&x| x)
|
|
|
|
.intersperse(", ")
|
|
|
|
.collect::<String>()
|
|
|
|
),
|
|
|
|
"s",
|
|
|
|
),
|
2022-12-18 16:17:46 +01:00
|
|
|
[only] => (only.to_string(), ""),
|
2022-05-27 15:20:21 -07:00
|
|
|
[] => unreachable!(),
|
|
|
|
};
|
|
|
|
let last_span = *arg_spans.last().unwrap();
|
|
|
|
let span: MultiSpan = arg_spans.into();
|
|
|
|
let mut err = struct_span_err!(
|
|
|
|
self.tcx().sess,
|
|
|
|
span,
|
|
|
|
E0109,
|
2022-06-01 16:55:30 -07:00
|
|
|
"{kind} arguments are not allowed on {this_type}",
|
2022-05-27 15:20:21 -07:00
|
|
|
);
|
|
|
|
err.span_label(last_span, format!("{kind} argument{s} not allowed"));
|
2022-06-19 17:54:19 -07:00
|
|
|
for (what, span) in types_and_spans {
|
|
|
|
err.span_label(span, format!("not allowed on {what}"));
|
2022-06-01 16:55:30 -07:00
|
|
|
}
|
2022-05-27 19:53:31 -07:00
|
|
|
extend(&mut err);
|
2022-05-27 15:20:21 -07:00
|
|
|
err.emit();
|
|
|
|
emitted = true;
|
|
|
|
}
|
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.
|
2022-09-29 22:44:24 +00:00
|
|
|
if let Some(b) = segment.args().bindings.first() {
|
2023-01-11 19:07:03 +00:00
|
|
|
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
2022-05-27 15:20:21 -07:00
|
|
|
return true;
|
2019-06-12 11:42:58 +03:00
|
|
|
}
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
2022-05-27 15:20:21 -07:00
|
|
|
emitted
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
|
|
|
|
pub fn def_ids_for_value_path_segments(
|
|
|
|
&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,
|
2019-04-20 19:46:19 +03:00
|
|
|
) -> Vec<PathSeg> {
|
2018-12-18 18:59:00 +00:00
|
|
|
// We need to extract the type parameters supplied by the user in
|
|
|
|
// the path `path`. Due to the current setup, this is a bit of a
|
|
|
|
// tricky-process; the problem is that resolve only tells us the
|
|
|
|
// 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>(...)
|
|
|
|
//
|
|
|
|
// In this case, the parameters are declared in the type space.
|
|
|
|
//
|
|
|
|
// 2. Reference to a constructor of an enum variant:
|
|
|
|
//
|
|
|
|
// enum E<T> { Foo(...) }
|
|
|
|
//
|
|
|
|
// In this case, the parameters are defined in the type space,
|
|
|
|
// but may be specified either on the type or the variant.
|
|
|
|
//
|
|
|
|
// 3. Reference to a fn item or a free constant:
|
|
|
|
//
|
|
|
|
// fn foo<T>() { }
|
|
|
|
//
|
|
|
|
// In this case, the path will again always have the form
|
|
|
|
// `a::b::foo::<T>` where only the final segment should have
|
|
|
|
// type parameters. However, in this case, those parameters are
|
|
|
|
// declared on a value, and hence are in the `FnSpace`.
|
|
|
|
//
|
|
|
|
// 4. Reference to a method or an associated constant:
|
|
|
|
//
|
|
|
|
// impl<A> SomeStruct<A> {
|
|
|
|
// fn foo<B>(...)
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// Here we can have a path like
|
|
|
|
// `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
|
|
|
|
// may appear in two places. The penultimate segment,
|
|
|
|
// `SomeStruct::<A>`, contains parameters in TypeSpace, and the
|
|
|
|
// final segment, `foo::<B>` contains parameters in fn space.
|
|
|
|
//
|
|
|
|
// The first step then is to categorize the segments appropriately.
|
|
|
|
|
|
|
|
let tcx = self.tcx();
|
|
|
|
|
|
|
|
assert!(!segments.is_empty());
|
|
|
|
let last = segments.len() - 1;
|
|
|
|
|
|
|
|
let mut path_segs = vec![];
|
|
|
|
|
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);
|
|
|
|
path_segs.push(PathSeg(generics_def_id, last));
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
};
|
|
|
|
path_segs.push(PathSeg(generics_def_id, index));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Case 3. Reference to a top-level value.
|
2022-03-29 17:11:12 +02:00
|
|
|
DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static(_) => {
|
2018-12-18 18:59:00 +00:00
|
|
|
path_segs.push(PathSeg(def_id, last));
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
|
|
|
|
}
|
|
|
|
path_segs.push(PathSeg(def_id, last));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
debug!("path_segs = {:?}", path_segs);
|
|
|
|
|
|
|
|
path_segs
|
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Check a type `Path` and convert it to a `Ty`.
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn res_to_ty(
|
|
|
|
&self,
|
|
|
|
opt_self_ty: Option<Ty<'tcx>>,
|
2019-12-01 16:08:58 +01:00
|
|
|
path: &hir::Path<'_>,
|
2022-12-14 23:53:05 +00:00
|
|
|
hir_id: hir::HirId,
|
2019-12-24 17:38:22 -05:00
|
|
|
permit_variants: bool,
|
|
|
|
) -> Ty<'tcx> {
|
2016-05-11 08:48:12 +03:00
|
|
|
let tcx = self.tcx();
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!(
|
|
|
|
"res_to_ty(res={:?}, opt_self_ty={:?}, path_segments={:?})",
|
|
|
|
path.res, opt_self_ty, path.segments
|
|
|
|
);
|
2016-05-12 14:19:26 -04:00
|
|
|
|
2016-11-25 13:21:19 +02:00
|
|
|
let span = path.span;
|
2019-04-20 19:36:05 +03:00
|
|
|
match path.res {
|
2022-09-06 17:37:00 +02:00
|
|
|
Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, 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();
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(item_segment.1.iter(), |err| {
|
|
|
|
err.note("`impl Trait` types can't have type parameters");
|
|
|
|
});
|
2018-07-03 19:38:14 +02:00
|
|
|
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
|
2022-09-17 21:35:47 +03:00
|
|
|
tcx.mk_opaque(did, substs)
|
2018-07-03 19:38:14 +02:00
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
Res::Def(
|
|
|
|
DefKind::Enum
|
|
|
|
| DefKind::TyAlias
|
|
|
|
| DefKind::Struct
|
|
|
|
| DefKind::Union
|
|
|
|
| DefKind::ForeignTy,
|
|
|
|
did,
|
|
|
|
) => {
|
2016-10-27 05:17:42 +03:00
|
|
|
assert_eq!(opt_self_ty, None);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(path.segments.split_last().unwrap().1.iter(), |_| {});
|
2017-01-25 17:32:44 +02:00
|
|
|
self.ast_path_to_ty(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 => {
|
2016-09-15 00:51:46 +03:00
|
|
|
// Convert "variant type" as if it were a real type.
|
|
|
|
// 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
|
|
|
|
2019-04-20 19:46:19 +03:00
|
|
|
let path_segs =
|
2022-10-29 16:19:57 +03:00
|
|
|
self.def_ids_for_value_path_segments(path.segments, None, kind, def_id, span);
|
2018-12-18 18:59:00 +00:00
|
|
|
let generic_segs: FxHashSet<_> =
|
|
|
|
path_segs.iter().map(|PathSeg(_, index)| index).collect();
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(
|
|
|
|
path.segments.iter().enumerate().filter_map(|(index, seg)| {
|
2019-12-24 17:38:22 -05:00
|
|
|
if !generic_segs.contains(&index) { Some(seg) } else { None }
|
2022-05-27 19:53:31 -07:00
|
|
|
}),
|
|
|
|
|err| {
|
|
|
|
err.note("enum variants can't have type parameters");
|
2019-12-24 17:38:22 -05:00
|
|
|
},
|
2022-05-27 19:53:31 -07:00
|
|
|
);
|
2018-12-18 18:59:00 +00:00
|
|
|
|
|
|
|
let PathSeg(def_id, index) = path_segs.last().unwrap();
|
|
|
|
self.ast_path_to_ty(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);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(path.segments.iter(), |err| {
|
|
|
|
if let Some(span) = tcx.def_ident_span(def_id) {
|
|
|
|
let name = tcx.item_name(def_id);
|
|
|
|
err.span_note(span, &format!("type parameter `{name}` defined here"));
|
|
|
|
}
|
|
|
|
});
|
2016-08-15 01:07:09 +03:00
|
|
|
|
2022-12-14 23:53:05 +00:00
|
|
|
match tcx.named_bound_var(hir_id) {
|
|
|
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
|
|
let name =
|
|
|
|
tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
|
|
|
|
let br = ty::BoundTy {
|
|
|
|
var: ty::BoundVar::from_u32(index),
|
|
|
|
kind: ty::BoundTyKind::Param(def_id, name),
|
|
|
|
};
|
|
|
|
tcx.mk_ty(ty::Bound(debruijn, br))
|
|
|
|
}
|
|
|
|
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
|
|
|
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()];
|
|
|
|
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
|
|
|
|
}
|
2023-02-18 03:28:43 +00:00
|
|
|
Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error_with_guaranteed(guar),
|
2022-12-14 23:53:05 +00:00
|
|
|
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
|
|
|
|
}
|
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);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(path.segments.iter(), |err| {
|
2023-02-16 00:06:51 +01:00
|
|
|
if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments {
|
2022-05-27 19:53:31 -07:00
|
|
|
err.span_suggestion_verbose(
|
|
|
|
ident.span.shrink_to_hi().to(args.span_ext),
|
|
|
|
"the `Self` type doesn't accept type parameters",
|
2022-06-13 15:48:40 +09:00
|
|
|
"",
|
2022-05-27 19:53:31 -07:00
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
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-02-07 01:29:48 -07:00
|
|
|
let ty = tcx.at(span).type_of(def_id).subst_identity();
|
2022-05-27 19:53:31 -07:00
|
|
|
let span_of_impl = tcx.span_of_impl(def_id);
|
|
|
|
self.prohibit_generics(path.segments.iter(), |err| {
|
|
|
|
let def_id = match *ty.kind() {
|
|
|
|
ty::Adt(self_def, _) => self_def.did(),
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
let type_name = tcx.item_name(def_id);
|
|
|
|
let span_of_ty = tcx.def_ident_span(def_id);
|
2022-05-31 12:53:52 -07:00
|
|
|
let generics = tcx.generics_of(def_id).count();
|
2022-05-27 19:53:31 -07:00
|
|
|
|
2022-05-31 12:53:52 -07:00
|
|
|
let msg = format!("`Self` is of type `{ty}`");
|
2022-05-27 19:53:31 -07:00
|
|
|
if let (Ok(i_sp), Some(t_sp)) = (span_of_impl, span_of_ty) {
|
|
|
|
let mut span: MultiSpan = vec![t_sp].into();
|
|
|
|
span.push_span_label(
|
|
|
|
i_sp,
|
2022-06-01 13:04:35 -07:00
|
|
|
&format!("`Self` is on type `{type_name}` in this `impl`"),
|
2022-05-31 12:53:52 -07:00
|
|
|
);
|
|
|
|
let mut postfix = "";
|
|
|
|
if generics == 0 {
|
2022-06-02 14:06:54 -07:00
|
|
|
postfix = ", which doesn't have generic parameters";
|
2022-05-31 12:53:52 -07:00
|
|
|
}
|
|
|
|
span.push_span_label(
|
|
|
|
t_sp,
|
|
|
|
&format!("`Self` corresponds to this type{postfix}"),
|
2022-05-27 19:53:31 -07:00
|
|
|
);
|
|
|
|
err.span_note(span, &msg);
|
|
|
|
} else {
|
|
|
|
err.note(&msg);
|
|
|
|
}
|
|
|
|
for segment in path.segments {
|
2022-05-31 12:53:52 -07:00
|
|
|
if let Some(args) = segment.args && segment.ident.name == kw::SelfUpper {
|
|
|
|
if generics == 0 {
|
|
|
|
// FIXME(estebank): we could also verify that the arguments being
|
|
|
|
// work for the `enum`, instead of just looking if it takes *any*.
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
segment.ident.span.shrink_to_hi().to(args.span_ext),
|
|
|
|
"the `Self` type doesn't accept type parameters",
|
2022-06-13 15:48:40 +09:00
|
|
|
"",
|
2022-05-31 12:53:52 -07:00
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
segment.ident.span,
|
|
|
|
format!(
|
|
|
|
"the `Self` type doesn't accept type parameters, use the \
|
|
|
|
concrete type's name `{type_name}` instead if you want to \
|
|
|
|
specify its type parameters"
|
|
|
|
),
|
2022-07-17 04:09:20 +09:00
|
|
|
type_name,
|
2022-05-31 12:53:52 -07:00
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
2022-05-27 19:53:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
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.
|
|
|
|
if forbid_generic && ty.needs_subst() {
|
2020-09-08 11:37:27 +02:00
|
|
|
let mut err = tcx.sess.struct_span_err(
|
|
|
|
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
|
|
|
}
|
2022-11-03 14:15:17 +08:00
|
|
|
tcx.ty_error_with_guaranteed(err.emit())
|
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);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {});
|
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
|
|
|
|
};
|
2019-12-24 17:38:22 -05:00
|
|
|
self.qpath_to_ty(
|
|
|
|
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);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.prohibit_generics(path.segments.iter(), |err| {
|
|
|
|
let name = prim_ty.name_str();
|
|
|
|
for segment in path.segments {
|
|
|
|
if let Some(args) = segment.args {
|
|
|
|
err.span_suggestion_verbose(
|
|
|
|
segment.ident.span.shrink_to_hi().to(args.span_ext),
|
2022-06-02 14:06:54 -07:00
|
|
|
&format!("primitive type `{name}` doesn't have generic parameters"),
|
2022-06-13 15:48:40 +09:00
|
|
|
"",
|
2022-05-27 19:53:31 -07:00
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
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,
|
2020-12-12 15:32:30 +01:00
|
|
|
hir::PrimTy::Int(it) => tcx.mk_mach_int(ty::int_ty(it)),
|
|
|
|
hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(ty::uint_ty(uit)),
|
|
|
|
hir::PrimTy::Float(ft) => tcx.mk_mach_float(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()
|
|
|
|
.sess
|
2022-12-25 00:43:50 +01:00
|
|
|
.delay_span_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);
|
|
|
|
self.tcx().ty_error_with_guaranteed(e)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
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
|
|
|
|
2021-03-26 17:40:15 -04:00
|
|
|
/// Parses the programmer's textual representation of a type into our
|
|
|
|
/// internal notion of a type.
|
2019-12-01 16:08:58 +01:00
|
|
|
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
2021-07-10 10:00:54 +02:00
|
|
|
self.ast_ty_to_ty_inner(ast_ty, false, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parses the programmer's textual representation of a type into our
|
2022-11-16 20:34:16 +00:00
|
|
|
/// internal notion of a type. This is meant to be used within a path.
|
2021-07-10 10:00:54 +02:00
|
|
|
pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
|
|
|
self.ast_ty_to_ty_inner(ast_ty, false, true)
|
2020-08-13 18:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
|
|
|
|
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
|
2022-06-28 15:18:07 +00:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2021-07-10 10:00:54 +02:00
|
|
|
fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, 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
|
|
|
|
2023-01-09 16:30:40 +00:00
|
|
|
let result_ty = match &ast_ty.kind {
|
|
|
|
hir::TyKind::Slice(ty) => tcx.mk_slice(self.ast_ty_to_ty(ty)),
|
|
|
|
hir::TyKind::Ptr(mt) => {
|
2021-09-30 19:38:50 +02:00
|
|
|
tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl })
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Ref(region, mt) => {
|
2017-01-13 15:09:56 +02:00
|
|
|
let r = self.ast_region_to_region(region, None);
|
2021-02-27 21:31:56 -05:00
|
|
|
debug!(?r);
|
2021-07-10 10:00:54 +02:00
|
|
|
let t = self.ast_ty_to_ty_inner(mt.ty, true, false);
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
hir::TyKind::Never => tcx.types.never,
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::TyKind::Tup(fields) => tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(t))),
|
|
|
|
hir::TyKind::BareFn(bf) => {
|
|
|
|
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);
|
2021-02-10 15:49:23 +00:00
|
|
|
|
2023-02-18 03:28:43 +00:00
|
|
|
tcx.mk_fn_ptr(self.ty_of_fn(
|
2020-10-26 14:18:31 -04:00
|
|
|
ast_ty.hir_id,
|
2020-03-22 18:50:30 -07:00
|
|
|
bf.unsafety,
|
|
|
|
bf.abi,
|
2021-09-30 19:38:50 +02:00
|
|
|
bf.decl,
|
2020-03-22 18:50:30 -07:00
|
|
|
None,
|
2021-02-10 15:49:23 +00:00
|
|
|
Some(ast_ty),
|
2023-02-18 03:28:43 +00:00
|
|
|
))
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
|
2021-07-10 10:00:54 +02:00
|
|
|
self.maybe_lint_bare_trait(ast_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
|
|
|
};
|
2023-02-06 23:53:24 +00:00
|
|
|
|
2023-02-18 03:28:43 +00:00
|
|
|
self.conv_object_ty_poly_trait_ref(ast_ty.span, 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);
|
2019-12-24 17:38:22 -05:00
|
|
|
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
|
2022-12-14 23:53:05 +00:00
|
|
|
self.res_to_ty(opt_self_ty, path, ast_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);
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = item_id.owner_id.to_def_id();
|
2020-05-10 11:57:58 +01:00
|
|
|
|
|
|
|
match opaque_ty.kind {
|
2022-05-20 15:29:45 -03:00
|
|
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
|
2022-09-06 17:37:00 +02:00
|
|
|
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, 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);
|
2021-07-10 10:00:54 +02:00
|
|
|
let ty = self.ast_ty_to_ty_inner(qself, false, true);
|
2022-05-27 19:53:31 -07:00
|
|
|
self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false)
|
2019-12-24 17:38:22 -05:00
|
|
|
.map(|(ty, _, _)| ty)
|
2020-05-05 23:02:09 -05:00
|
|
|
.unwrap_or_else(|_| tcx.ty_error())
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2023-01-09 16:30:40 +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));
|
2020-10-26 14:18:31 -04:00
|
|
|
let (substs, _) = self.create_substs_for_ast_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
|
|
|
&GenericArgs::none(),
|
|
|
|
true,
|
|
|
|
None,
|
2022-11-04 16:28:01 +00:00
|
|
|
ty::BoundConstness::NotConst,
|
2020-08-04 14:34:24 +01:00
|
|
|
);
|
2023-02-07 01:29:48 -07:00
|
|
|
tcx.at(span).type_of(def_id).subst(tcx, substs)
|
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 {
|
|
|
|
&hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span),
|
|
|
|
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
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-02-08 12:28:03 +11:00
|
|
|
tcx.mk_array_with_const_len(self.ast_ty_to_ty(ty), length)
|
2014-01-29 00:05:11 -05:00
|
|
|
}
|
2023-01-09 16:30:40 +00:00
|
|
|
hir::TyKind::Typeof(e) => {
|
2023-02-07 01:29:48 -07:00
|
|
|
let ty_erased = tcx.type_of(e.def_id).subst_identity();
|
2022-08-05 23:51:33 +00:00
|
|
|
let ty = tcx.fold_regions(ty_erased, |r, _| {
|
|
|
|
if r.is_erased() { tcx.lifetimes.re_static } else { r }
|
|
|
|
});
|
2022-04-07 22:46:53 +04:00
|
|
|
let span = ast_ty.span;
|
2023-01-14 22:55:27 +00:00
|
|
|
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
|
|
|
|
(ty, Some((span, Applicability::MachineApplicable)))
|
|
|
|
} else {
|
|
|
|
(ty, None)
|
|
|
|
};
|
|
|
|
tcx.sess.emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
|
2022-04-07 22:46:53 +04:00
|
|
|
|
|
|
|
ty
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
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.
|
2019-06-06 01:55:34 +01:00
|
|
|
self.ty_infer(None, ast_ty.span)
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2020-05-05 23:02:09 -05:00
|
|
|
hir::TyKind::Err => tcx.ty_error(),
|
2016-05-12 14:19:26 -04:00
|
|
|
};
|
|
|
|
|
2017-09-16 02:33:41 +03:00
|
|
|
self.record_ty(ast_ty.hir_id, result_ty, ast_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
|
|
|
|
2022-09-06 17:24:36 -03:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2020-10-26 14:18:31 -04:00
|
|
|
fn impl_trait_ty_to_ty(
|
2019-12-01 16:08:58 +01:00
|
|
|
&self,
|
|
|
|
def_id: DefId,
|
|
|
|
lifetimes: &[hir::GenericArg<'_>],
|
2022-05-20 15:29:45 -03:00
|
|
|
origin: OpaqueTyOrigin,
|
2022-09-06 17:37:00 +02:00
|
|
|
in_trait: bool,
|
2019-12-01 16:08:58 +01:00
|
|
|
) -> Ty<'tcx> {
|
2017-10-15 13:43:06 -07:00
|
|
|
debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
|
|
|
|
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);
|
|
|
|
|
|
|
|
debug!("impl_trait_ty_to_ty: generics={:?}", generics);
|
2019-02-26 09:30:34 +08:00
|
|
|
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
|
2018-05-16 11:56:50 +03:00
|
|
|
if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
|
|
|
|
// Our own parameters are the resolved lifetimes.
|
2022-10-23 20:38:34 +00:00
|
|
|
let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() };
|
|
|
|
let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() };
|
|
|
|
self.ast_region_to_region(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
|
|
|
});
|
2019-03-21 17:55:09 +00:00
|
|
|
debug!("impl_trait_ty_to_ty: substs={:?}", substs);
|
2017-10-15 13:43:06 -07:00
|
|
|
|
2022-09-06 17:37:00 +02:00
|
|
|
if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) }
|
2017-10-15 13:43:06 -07:00
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
|
2019-09-26 17:25:31 +01:00
|
|
|
match ty.kind {
|
2018-07-11 22:41:03 +08:00
|
|
|
hir::TyKind::Infer if expected_ty.is_some() => {
|
2017-09-16 02:33:41 +03:00
|
|
|
self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
|
|
|
|
expected_ty.unwrap()
|
|
|
|
}
|
2017-01-25 17:32:44 +02:00
|
|
|
_ => self.ast_ty_to_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
|
|
|
|
2022-10-20 09:39:09 +00:00
|
|
|
#[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
|
2019-12-24 17:38:22 -05:00
|
|
|
pub fn ty_of_fn(
|
|
|
|
&self,
|
2020-10-26 14:18:31 -04:00
|
|
|
hir_id: hir::HirId,
|
2019-12-24 17:38:22 -05:00
|
|
|
unsafety: hir::Unsafety,
|
|
|
|
abi: abi::Abi,
|
2019-12-01 16:08:58 +01:00
|
|
|
decl: &hir::FnDecl<'_>,
|
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();
|
2020-10-26 14:18:31 -04:00
|
|
|
let bound_vars = tcx.late_bound_vars(hir_id);
|
|
|
|
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 && !self.allow_ty_infer() {
|
|
|
|
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()));
|
|
|
|
return suggested_ty;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only visit the type looking for `_` if we didn't fix the type above
|
|
|
|
visitor.visit_ty(a);
|
|
|
|
self.ty_of_arg(a, None)
|
|
|
|
})
|
|
|
|
.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
|
|
|
|
&& !self.allow_ty_infer()
|
|
|
|
&& 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()));
|
|
|
|
suggested_ty
|
|
|
|
} else {
|
|
|
|
visitor.visit_ty(output);
|
|
|
|
self.ast_ty_to_ty(output)
|
|
|
|
}
|
2019-12-23 14:16:34 -08:00
|
|
|
}
|
2020-02-15 12:10:59 +09:00
|
|
|
hir::FnRetTy::DefaultReturn(..) => tcx.mk_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
|
|
|
|
2023-02-16 16:05:08 +11:00
|
|
|
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, 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
|
|
|
|
2022-03-27 19:43:05 -07:00
|
|
|
if !self.allow_ty_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
|
2020-03-24 11:35:48 -07:00
|
|
|
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of
|
|
|
|
// `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(
|
|
|
|
&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
|
|
|
}
|
|
|
|
|
|
|
|
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 =
|
|
|
|
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();
|
|
|
|
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| {
|
|
|
|
struct_span_err!(
|
2019-12-24 17:38:22 -05:00
|
|
|
tcx.sess,
|
|
|
|
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,
|
|
|
|
fn_hir_id: hir::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 = tcx.hir();
|
|
|
|
|
|
|
|
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
|
|
|
|
hir.get(fn_hir_id) else { return None };
|
2023-01-20 15:59:56 +00:00
|
|
|
let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
|
2022-03-27 19:43:05 -07:00
|
|
|
|
2022-10-20 09:39:09 +00:00
|
|
|
let trait_ref = self.instantiate_mono_trait_ref(
|
|
|
|
i.of_trait.as_ref()?,
|
|
|
|
self.ast_ty_to_ty(i.self_ty),
|
|
|
|
ty::BoundConstness::NotConst,
|
|
|
|
);
|
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-01-18 16:52:47 -07:00
|
|
|
let fn_sig = tcx.fn_sig(assoc.def_id).subst(
|
2022-03-27 19:43:05 -07:00
|
|
|
tcx,
|
2022-04-24 23:32:59 -07:00
|
|
|
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
|
2022-03-27 19:43:05 -07:00
|
|
|
);
|
|
|
|
|
2022-03-27 19:43:08 -07:00
|
|
|
let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
|
|
|
|
|
2022-04-24 23:32:59 -07:00
|
|
|
Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty))
|
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>,
|
2022-01-23 12:34:26 -06:00
|
|
|
generate_err: impl Fn(&str) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
2020-07-25 02:03:50 -07:00
|
|
|
) {
|
|
|
|
for br in referenced_regions.difference(&constrained_regions) {
|
|
|
|
let br_name = match *br {
|
2022-10-17 22:08:15 -04:00
|
|
|
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
|
2022-05-11 22:49:39 +02:00
|
|
|
"an anonymous lifetime".to_string()
|
|
|
|
}
|
2020-07-25 02:03:50 -07:00
|
|
|
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut err = generate_err(&br_name);
|
|
|
|
|
2022-10-17 22:08:15 -04: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
|
|
|
|
2018-01-22 17:36:43 -05:00
|
|
|
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
|
|
|
|
/// use to summarize this type. The basic idea is that we will use the bound the user
|
|
|
|
/// 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`.
|
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
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
|
2014-12-07 11:10:48 -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) {
|
2020-08-27 20:09:22 +10:00
|
|
|
tcx.sess.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
|
|
|
}
|
2021-07-10 10:00:54 +02:00
|
|
|
|
2022-06-22 23:06:34 +01:00
|
|
|
/// Make sure that we are in the condition to suggest the blanket implementation.
|
2022-08-10 03:39:41 +00:00
|
|
|
fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) {
|
2022-05-15 01:28:10 +02:00
|
|
|
let tcx = self.tcx();
|
2022-09-20 14:11:23 +09:00
|
|
|
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
|
2022-05-15 01:28:10 +02:00
|
|
|
if let hir::Node::Item(hir::Item {
|
|
|
|
kind:
|
|
|
|
hir::ItemKind::Impl(hir::Impl {
|
2022-06-22 23:06:34 +01:00
|
|
|
self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, ..
|
2022-05-15 01:28:10 +02:00
|
|
|
}),
|
|
|
|
..
|
2022-06-22 23:06:34 +01:00
|
|
|
}) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
|
2022-05-15 01:28:10 +02:00
|
|
|
{
|
2022-06-22 23:06:34 +01:00
|
|
|
if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let of_trait_span = of_trait_ref.path.span;
|
|
|
|
// make sure that we are not calling unwrap to abort during the compilation
|
|
|
|
let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; };
|
|
|
|
let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; };
|
|
|
|
// check if the trait has generics, to make a correct suggestion
|
|
|
|
let param_name = generics.params.next_type_param_name(None);
|
|
|
|
|
|
|
|
let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
|
|
|
|
(span, format!(", {}: {}", param_name, impl_trait_name))
|
2022-05-15 01:28:10 +02:00
|
|
|
} else {
|
2022-06-22 23:06:34 +01:00
|
|
|
(generics.span, format!("<{}: {}>", param_name, impl_trait_name))
|
2022-05-15 01:28:10 +02:00
|
|
|
};
|
2022-06-22 23:06:34 +01:00
|
|
|
diag.multipart_suggestion(
|
|
|
|
format!("alternatively use a blanket \
|
|
|
|
implementation to implement `{of_trait_name}` for \
|
|
|
|
all types that also implement `{impl_trait_name}`"),
|
|
|
|
vec![
|
|
|
|
(self_ty.span, param_name),
|
|
|
|
add_generic_sugg,
|
|
|
|
],
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
);
|
2022-05-15 01:28:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-10 10:00:54 +02:00
|
|
|
fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
|
|
|
|
let tcx = self.tcx();
|
|
|
|
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
|
|
|
|
self_ty.kind
|
|
|
|
{
|
2021-11-01 10:01:42 +01:00
|
|
|
let needs_bracket = in_path
|
|
|
|
&& !tcx
|
2021-07-10 10:00:54 +02:00
|
|
|
.sess
|
|
|
|
.source_map()
|
|
|
|
.span_to_prev_source(self_ty.span)
|
|
|
|
.ok()
|
|
|
|
.map_or(false, |s| s.trim_end().ends_with('<'));
|
2021-11-01 10:01:42 +01:00
|
|
|
|
|
|
|
let is_global = poly_trait_ref.trait_ref.path.is_global();
|
2022-10-11 16:17:59 +00:00
|
|
|
|
|
|
|
let mut sugg = Vec::from_iter([(
|
|
|
|
self_ty.span.shrink_to_lo(),
|
|
|
|
format!(
|
|
|
|
"{}dyn {}",
|
|
|
|
if needs_bracket { "<" } else { "" },
|
|
|
|
if is_global { "(" } else { "" },
|
2021-11-01 10:01:42 +01:00
|
|
|
),
|
2022-10-11 16:17:59 +00:00
|
|
|
)]);
|
|
|
|
|
|
|
|
if is_global || needs_bracket {
|
|
|
|
sugg.push((
|
2021-11-01 10:01:42 +01:00
|
|
|
self_ty.span.shrink_to_hi(),
|
|
|
|
format!(
|
|
|
|
"{}{}",
|
|
|
|
if is_global { ")" } else { "" },
|
|
|
|
if needs_bracket { ">" } else { "" },
|
|
|
|
),
|
2022-10-11 16:17:59 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2021-10-17 19:10:21 +02:00
|
|
|
if self_ty.span.edition() >= Edition::Edition2021 {
|
2021-07-10 10:00:54 +02:00
|
|
|
let msg = "trait objects must include the `dyn` keyword";
|
|
|
|
let label = "add `dyn` keyword before this trait";
|
2022-05-15 01:28:10 +02:00
|
|
|
let mut diag =
|
|
|
|
rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg);
|
2022-12-23 00:13:47 +00:00
|
|
|
if self_ty.span.can_be_used_for_suggestions() {
|
|
|
|
diag.multipart_suggestion_verbose(
|
|
|
|
label,
|
|
|
|
sugg,
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
|
|
|
}
|
2022-06-22 23:06:34 +01:00
|
|
|
// check if the impl trait that we are considering is a impl of a local trait
|
2022-06-29 23:31:10 +00:00
|
|
|
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
|
2022-05-15 01:28:10 +02:00
|
|
|
diag.emit();
|
2021-07-10 10:00:54 +02:00
|
|
|
} else {
|
|
|
|
let msg = "trait objects without an explicit `dyn` are deprecated";
|
|
|
|
tcx.struct_span_lint_hir(
|
|
|
|
BARE_TRAIT_OBJECTS,
|
|
|
|
self_ty.hir_id,
|
|
|
|
self_ty.span,
|
2022-09-16 11:01:02 +04:00
|
|
|
msg,
|
2021-07-10 10:00:54 +02:00
|
|
|
|lint| {
|
2022-09-16 11:01:02 +04:00
|
|
|
lint.multipart_suggestion_verbose(
|
2022-05-15 01:28:10 +02:00
|
|
|
"use `dyn`",
|
|
|
|
sugg,
|
|
|
|
Applicability::MachineApplicable,
|
|
|
|
);
|
2022-09-16 11:01:02 +04:00
|
|
|
self.maybe_lint_blanket_trait_impl(&self_ty, lint);
|
|
|
|
lint
|
2021-07-10 10:00:54 +02:00
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-02 18:07:47 +03:00
|
|
|
}
|