summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_hir_analysis
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis')
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs45
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs319
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs33
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs215
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs396
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs277
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs257
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs53
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs139
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs64
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs145
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs194
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs126
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs285
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs65
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs46
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/terms.rs11
44 files changed, 1633 insertions, 1511 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 166760166..597cae6ff 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,6 +1,9 @@
hir_analysis_ambiguous_lifetime_bound =
ambiguous lifetime bound, explicit lifetime bound required
+hir_analysis_assoc_bound_on_const = expected associated type, found {$descr}
+ .note = trait bounds not allowed on {$descr}
+
hir_analysis_assoc_type_binding_not_allowed =
associated type bindings are not allowed here
.label = associated type not allowed here
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index b13de7701..ba152cd48 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -13,7 +13,7 @@ use crate::astconv::{
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
};
use crate::bounds::Bounds;
-use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
+use crate::errors;
impl<'tcx> dyn AstConv<'tcx> + '_ {
/// Sets `implicitly_sized` to true on `Bounds` if necessary
@@ -35,7 +35,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
if unbound.is_none() {
unbound = Some(&ptr.trait_ref);
} else {
- tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+ tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
}
}
}
@@ -326,7 +326,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
dup_bindings
.entry(assoc_item.def_id)
.and_modify(|prev_span| {
- tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
+ tcx.sess.emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
span: binding.span,
prev_span: *prev_span,
item_name: binding.item_name,
@@ -341,8 +341,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// If we have an method return type bound, then we need to substitute
// the method's early bound params with suitable late-bound params.
let mut num_bound_vars = candidate.bound_vars().len();
- let substs =
- candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| {
+ let args =
+ candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
let subst = match param.kind {
ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound(
tcx,
@@ -422,7 +422,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// params (and trait ref's late bound params). This logic is very similar to
// `Predicate::subst_supertrait`, and it's no coincidence why.
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
- let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs);
+ let subst_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
let bound_vars = tcx.late_bound_vars(binding.hir_id);
ty::Binder::bind_with_vars(subst_output, bound_vars)
@@ -438,16 +438,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
infer_args: false,
};
- let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+ let args_trait_ref_and_assoc_item = self.create_args_for_associated_item(
path_span,
assoc_item.def_id,
&item_segment,
- trait_ref.substs,
+ trait_ref.args,
);
- debug!(?substs_trait_ref_and_assoc_item);
+ debug!(?args_trait_ref_and_assoc_item);
- tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
+ tcx.mk_alias_ty(assoc_item.def_id, args_trait_ref_and_assoc_item)
})
};
@@ -488,6 +488,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
}
}
+ let assoc_item_def_id = projection_ty.skip_binder().def_id;
+ let def_kind = tcx.def_kind(assoc_item_def_id);
match binding.kind {
ConvertedBindingKind::Equality(..) if return_type_notation => {
return Err(self.tcx().sess.emit_err(
@@ -499,11 +501,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// the "projection predicate" for:
//
// `<T as Iterator>::Item = u32`
- let assoc_item_def_id = projection_ty.skip_binder().def_id;
- let def_kind = tcx.def_kind(assoc_item_def_id);
match (def_kind, term.unpack()) {
- (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
- | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (),
+ (DefKind::AssocTy, ty::TermKind::Ty(_))
+ | (DefKind::AssocConst, ty::TermKind::Const(_)) => (),
(_, _) => {
let got = if let Some(_) = term.ty() { "type" } else { "constant" };
let expected = tcx.def_descr(assoc_item_def_id);
@@ -516,7 +516,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
format!("{expected} defined here"),
);
- if let hir::def::DefKind::AssocConst = def_kind
+ if let DefKind::AssocConst = def_kind
&& let Some(t) = term.ty() && (t.is_enum() || t.references_error())
&& tcx.features().associated_const_equality {
err.span_suggestion(
@@ -528,12 +528,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
}
let reported = err.emit();
term = match def_kind {
- hir::def::DefKind::AssocTy => Ty::new_error(tcx, reported).into(),
- hir::def::DefKind::AssocConst => ty::Const::new_error(
+ DefKind::AssocTy => Ty::new_error(tcx, reported).into(),
+ DefKind::AssocConst => ty::Const::new_error(
tcx,
reported,
tcx.type_of(assoc_item_def_id)
- .subst(tcx, projection_ty.skip_binder().substs),
+ .instantiate(tcx, projection_ty.skip_binder().args),
)
.into(),
_ => unreachable!(),
@@ -548,6 +548,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
);
}
ConvertedBindingKind::Constraint(ast_bounds) => {
+ match def_kind {
+ DefKind::AssocTy => {}
+ _ => {
+ return Err(tcx.sess.emit_err(errors::AssocBoundOnConst {
+ span: assoc_ident.span,
+ descr: tcx.def_descr(assoc_item_def_id),
+ }));
+ }
+ }
// "Desugar" a constraint like `T: Iterator<Item: Debug>` to
//
// `<T as Iterator>::Item: Debug`
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index ddf99853b..bd311c98f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -123,7 +123,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
.filter_map(|item| {
- if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
Some(item.name)
} else {
None
@@ -164,7 +164,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.tcx().associated_items(*trait_def_id).in_definition_order()
})
.filter_map(|item| {
- if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type {
Some(item.name)
} else {
None
@@ -197,7 +197,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
- err.span_label(span, format!("associated type `{}` not found", assoc_name));
+ err.span_label(span, format!("associated type `{assoc_name}` not found"));
err.emit()
}
@@ -247,7 +247,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"the candidate".into()
};
- let impl_ty = tcx.at(span).type_of(impl_).subst_identity();
+ let impl_ty = tcx.at(span).type_of(impl_).instantiate_identity();
let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
if let Some(span) = note_span {
@@ -295,7 +295,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let type_candidates = candidates
.iter()
.take(limit)
- .map(|&(impl_, _)| format!("- `{}`", tcx.at(span).type_of(impl_).subst_identity()))
+ .map(|&(impl_, _)| {
+ format!("- `{}`", tcx.at(span).type_of(impl_).instantiate_identity())
+ })
.collect::<Vec<_>>()
.join("\n");
let additional_types = if candidates.len() > limit {
@@ -356,13 +358,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// `<Foo as Iterator>::Item = String`.
let projection_ty = pred.skip_binder().projection_ty;
- let substs_with_infer_self = tcx.mk_substs_from_iter(
+ let args_with_infer_self = tcx.mk_args_from_iter(
std::iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into())
- .chain(projection_ty.substs.iter().skip(1)),
+ .chain(projection_ty.args.iter().skip(1)),
);
let quiet_projection_ty =
- tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
+ tcx.mk_alias_ty(projection_ty.def_id, args_with_infer_self);
let term = pred.skip_binder().term;
@@ -391,7 +393,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.into_iter()
.map(|error| error.root_obligation.predicate)
.filter_map(format_pred)
- .map(|(p, _)| format!("`{}`", p))
+ .map(|(p, _)| format!("`{p}`"))
.collect();
bounds.sort();
bounds.dedup();
@@ -650,7 +652,7 @@ pub(crate) fn fn_trait_to_string(
}
.map(|s| {
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
- if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
+ if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
})
.ok(),
_ => None,
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 39d1d1f2d..1372cc896 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -11,7 +11,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
use rustc_middle::ty::{
- self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
+ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
};
use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
use rustc_span::{symbol::kw, Span};
@@ -76,12 +76,12 @@ fn generic_arg_mismatch_err(
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
let param_name = tcx.hir().ty_param_name(param_local_id);
- let param_type = tcx.type_of(param.def_id).subst_identity();
+ let param_type = tcx.type_of(param.def_id).instantiate_identity();
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
tcx.def_span(src_def_id),
"consider changing this type parameter to a const parameter",
- format!("const {}: {}", param_name, param_type),
+ format!("const {param_name}: {param_type}"),
Applicability::MaybeIncorrect,
);
};
@@ -102,7 +102,7 @@ fn generic_arg_mismatch_err(
err.span_suggestion(
arg.span(),
"array type provided where a `usize` was expected, try",
- format!("{{ {} }}", snippet),
+ format!("{{ {snippet} }}"),
Applicability::MaybeIncorrect,
);
}
@@ -130,7 +130,7 @@ fn generic_arg_mismatch_err(
} else {
(arg.descr(), param.kind.descr())
};
- err.note(format!("{} arguments must be provided before {} arguments", first, last));
+ err.note(format!("{first} arguments must be provided before {last} arguments"));
if let Some(help) = help {
err.help(help);
}
@@ -146,14 +146,14 @@ fn generic_arg_mismatch_err(
///
/// To start, we are given the `def_id` of the thing we are
/// creating the substitutions for, and a partial set of
-/// substitutions `parent_substs`. In general, the substitutions
+/// substitutions `parent_args`. In general, the substitutions
/// for an item begin with substitutions for all the "parents" of
/// that item -- e.g., for a method it might include the
/// parameters from the impl.
///
/// Therefore, the method begins by walking down these parents,
/// starting with the outermost parent and proceed inwards until
-/// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
+/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
/// first to see if the parent's substitutions are listed in there. If so,
/// we can append those and move on. Otherwise, it invokes the
/// three callback functions:
@@ -168,15 +168,15 @@ fn generic_arg_mismatch_err(
/// instantiate a `GenericArg`.
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
/// creates a suitable inference variable.
-pub fn create_substs_for_generic_args<'tcx, 'a>(
+pub fn create_args_for_parent_generic_args<'tcx, 'a>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- parent_substs: &[subst::GenericArg<'tcx>],
+ parent_args: &[ty::GenericArg<'tcx>],
has_self: bool,
self_ty: Option<Ty<'tcx>>,
arg_count: &GenericArgCountResult,
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
-) -> SubstsRef<'tcx> {
+) -> GenericArgsRef<'tcx> {
// Collect the segments of the path; we need to substitute arguments
// for parameters throughout the entire path (wherever there are
// generic parameters).
@@ -191,27 +191,27 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
// We manually build up the substitution, rather than using convenience
// methods in `subst.rs`, so that we can iterate over the arguments and
// parameters in lock-step linearly, instead of trying to match each pair.
- let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
+ let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
// Iterate over each segment of the path.
while let Some((def_id, defs)) = stack.pop() {
let mut params = defs.params.iter().peekable();
// If we have already computed substitutions for parents, we can use those directly.
while let Some(&param) = params.peek() {
- if let Some(&kind) = parent_substs.get(param.index as usize) {
- substs.push(kind);
+ if let Some(&kind) = parent_args.get(param.index as usize) {
+ args.push(kind);
params.next();
} else {
break;
}
}
- // `Self` is handled first, unless it's been handled in `parent_substs`.
+ // `Self` is handled first, unless it's been handled in `parent_args`.
if has_self {
if let Some(&param) = params.peek() {
if param.index == 0 {
if let GenericParamDefKind::Type { .. } = param.kind {
- substs.push(
+ args.push(
self_ty
.map(|ty| ty.into())
.unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
@@ -226,7 +226,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter());
- let mut args = args_iter.clone().peekable();
+ let mut args_iter = args_iter.clone().peekable();
// If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
// If we later encounter a lifetime, we know that the arguments were provided in the
@@ -239,7 +239,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
// provided, matching them with the generic parameters we expect.
// Mismatches can occur as a result of elided lifetimes, or for malformed
// input. We try to handle both sensibly.
- match (args.peek(), params.peek()) {
+ match (args_iter.peek(), params.peek()) {
(Some(&arg), Some(&param)) => {
match (arg, &param.kind, arg_count.explicit_late_bound) {
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
@@ -253,8 +253,8 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
GenericParamDefKind::Const { .. },
_,
) => {
- substs.push(ctx.provided_kind(param, arg));
- args.next();
+ args.push(ctx.provided_kind(param, arg));
+ args_iter.next();
params.next();
}
(
@@ -264,7 +264,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
) => {
// We expected a lifetime argument, but got a type or const
// argument. That means we're inferring the lifetimes.
- substs.push(ctx.inferred_kind(None, param, infer_args));
+ args.push(ctx.inferred_kind(None, param, infer_args));
force_infer_lt = Some((arg, param));
params.next();
}
@@ -273,7 +273,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
// the presence of explicit late bounds. This is most likely
// due to the presence of the explicit bound so we're just going to
// ignore it.
- args.next();
+ args_iter.next();
}
(_, _, _) => {
// We expected one kind of parameter, but the user provided
@@ -304,7 +304,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
"reorder the arguments: {}: `<{}>`",
param_types_present
.into_iter()
- .map(|ord| format!("{}s", ord))
+ .map(|ord| format!("{ord}s"))
.collect::<Vec<String>>()
.join(", then "),
ordered_params
@@ -327,7 +327,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
// errors. In this case, we're simply going to ignore the argument
// and any following arguments. The rest of the parameters will be
// inferred.
- while args.next().is_some() {}
+ while args_iter.next().is_some() {}
}
}
}
@@ -360,7 +360,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
(None, Some(&param)) => {
// If there are fewer arguments than parameters, it means
// we're inferring the remaining arguments.
- substs.push(ctx.inferred_kind(Some(&substs), param, infer_args));
+ args.push(ctx.inferred_kind(Some(&args), param, infer_args));
params.next();
}
@@ -369,7 +369,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
}
}
- tcx.mk_substs(&substs)
+ tcx.mk_args(&args)
}
/// Checks that the correct number of generic arguments have been provided.
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index 05a3ab63d..1bd1270be 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -34,9 +34,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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))
+ (span, format!(", {param_name}: {impl_trait_name}"))
} else {
- (generics.span, format!("<{}: {}>", param_name, impl_trait_name))
+ (generics.span, format!("<{param_name}: {impl_trait_name}>"))
};
diag.multipart_suggestion(
format!("alternatively use a blanket \
@@ -86,7 +86,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
));
}
- if self_ty.span.edition().rust_2021() {
+ if self_ty.span.edition().at_least_rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 3d6984628..668763f9b 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -9,7 +9,7 @@ mod lint;
mod object_safety;
use crate::astconv::errors::prohibit_assoc_ty_binding;
-use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
+use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args};
use crate::bounds::Bounds;
use crate::collect::HirPlaceholderCollector;
use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed};
@@ -29,9 +29,10 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+ self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
+};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, Ident, Symbol};
@@ -220,14 +221,14 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
&mut self,
param: &ty::GenericParamDef,
arg: &GenericArg<'_>,
- ) -> subst::GenericArg<'tcx>;
+ ) -> ty::GenericArg<'tcx>;
fn inferred_kind(
&mut self,
- substs: Option<&[subst::GenericArg<'tcx>]>,
+ args: Option<&[ty::GenericArg<'tcx>]>,
param: &ty::GenericParamDef,
infer_args: bool,
- ) -> subst::GenericArg<'tcx>;
+ ) -> ty::GenericArg<'tcx>;
}
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
@@ -291,13 +292,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// 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`.
- pub fn ast_path_substs_for_ty(
+ pub fn ast_path_args_for_ty(
&self,
span: Span,
def_id: DefId,
item_segment: &hir::PathSegment<'_>,
- ) -> SubstsRef<'tcx> {
- let (substs, _) = self.create_substs_for_ast_path(
+ ) -> GenericArgsRef<'tcx> {
+ let (args, _) = self.create_args_for_ast_path(
span,
def_id,
&[],
@@ -311,7 +312,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
}
- substs
+ args
}
/// Given the type/lifetime/const arguments provided to some path (along with
@@ -330,7 +331,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// 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
+ /// parameters are returned in the `GenericArgsRef`, the associated type bindings like
/// `Output = u32` are returned from `create_assoc_bindings_for_generic_args`.
///
/// Note that the type listing given here is *exactly* what the user provided.
@@ -341,22 +342,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// <Vec<u8> as Iterable<u8>>::Iter::<'a>
/// ```
///
- /// We have the parent substs are the substs for the parent trait:
+ /// We have the parent args are the args 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
+ /// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two
/// lists: `[Vec<u8>, u8, 'a]`.
#[instrument(level = "debug", skip(self, span), ret)]
- fn create_substs_for_ast_path<'a>(
+ fn create_args_for_ast_path<'a>(
&self,
span: Span,
def_id: DefId,
- parent_substs: &[subst::GenericArg<'tcx>],
+ parent_args: &[ty::GenericArg<'tcx>],
seg: &hir::PathSegment<'_>,
generic_args: &'a hir::GenericArgs<'_>,
infer_args: bool,
self_ty: Option<Ty<'tcx>>,
constness: ty::BoundConstness,
- ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
+ ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
// 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).
@@ -369,7 +370,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if generics.parent.is_some() {
// The parent is a trait so it should have at least one subst
// for the `Self` type.
- assert!(!parent_substs.is_empty())
+ assert!(!parent_args.is_empty())
} else {
// This item (presumably a trait) needs a self-type.
assert!(self_ty.is_some());
@@ -395,7 +396,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// here and so associated type bindings will be handled regardless of whether there are any
// non-`Self` generic parameters.
if generics.params.is_empty() {
- return (tcx.mk_substs(parent_substs), arg_count);
+ return (tcx.mk_args(parent_args), arg_count);
}
struct SubstsForAstPathCtxt<'a, 'tcx> {
@@ -421,7 +422,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut self,
param: &ty::GenericParamDef,
arg: &GenericArg<'_>,
- ) -> subst::GenericArg<'tcx> {
+ ) -> ty::GenericArg<'tcx> {
let tcx = self.astconv.tcx();
let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
@@ -483,10 +484,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
fn inferred_kind(
&mut self,
- substs: Option<&[subst::GenericArg<'tcx>]>,
+ args: Option<&[ty::GenericArg<'tcx>]>,
param: &ty::GenericParamDef,
infer_args: bool,
- ) -> subst::GenericArg<'tcx> {
+ ) -> ty::GenericArg<'tcx> {
let tcx = self.astconv.tcx();
match param.kind {
GenericParamDefKind::Lifetime => self
@@ -506,15 +507,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericParamDefKind::Type { has_default, .. } => {
if !infer_args && has_default {
// No type parameter provided, but a default exists.
- let substs = substs.unwrap();
- if substs.iter().any(|arg| match arg.unpack() {
+ let args = args.unwrap();
+ if args.iter().any(|arg| match arg.unpack() {
GenericArgKind::Type(ty) => ty.references_error(),
_ => false,
}) {
// Avoid ICE #86756 when type error recovery goes awry.
return Ty::new_misc_error(tcx).into();
}
- tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
+ tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into()
} else if infer_args {
self.astconv.ty_infer(Some(param), self.span).into()
} else {
@@ -531,8 +532,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Err(guar) = ty.error_reported() {
return ty::Const::new_error(tcx, guar, ty).into();
}
+ // FIXME(effects) see if we should special case effect params here
if !infer_args && has_default {
- tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
+ tcx.const_param_default(param.def_id)
+ .instantiate(tcx, args.unwrap())
+ .into()
} else {
if infer_args {
self.astconv.ct_infer(ty, Some(param), self.span).into()
@@ -546,7 +550,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
- let mut substs_ctx = SubstsForAstPathCtxt {
+ let mut args_ctx = SubstsForAstPathCtxt {
astconv: self,
def_id,
span,
@@ -554,14 +558,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
inferred_params: vec![],
infer_args,
};
- let substs = create_substs_for_generic_args(
+ let args = create_args_for_parent_generic_args(
tcx,
def_id,
- parent_substs,
+ parent_args,
self_ty.is_some(),
self_ty,
&arg_count,
- &mut substs_ctx,
+ &mut args_ctx,
);
if let ty::BoundConstness::ConstIfConst = constness
@@ -570,7 +574,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
}
- (substs, arg_count)
+ (args, arg_count)
}
fn create_assoc_bindings_for_generic_args<'a>(
@@ -617,21 +621,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assoc_bindings
}
- pub fn create_substs_for_associated_item(
+ pub fn create_args_for_associated_item(
&self,
span: Span,
item_def_id: DefId,
item_segment: &hir::PathSegment<'_>,
- parent_substs: SubstsRef<'tcx>,
- ) -> SubstsRef<'tcx> {
+ parent_args: GenericArgsRef<'tcx>,
+ ) -> GenericArgsRef<'tcx> {
debug!(
- "create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
+ "create_args_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
span, item_def_id, item_segment
);
- let (args, _) = self.create_substs_for_ast_path(
+ let (args, _) = self.create_args_for_ast_path(
span,
item_def_id,
- parent_substs,
+ parent_args,
item_segment,
item_segment.args(),
item_segment.infer_args,
@@ -656,7 +660,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
trait_ref: &hir::TraitRef<'_>,
self_ty: Ty<'tcx>,
- constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
@@ -666,7 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_ref.path.segments.last().unwrap(),
true,
- constness,
+ ty::BoundConstness::NotConst,
)
}
@@ -687,7 +690,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
- let (substs, arg_count) = self.create_substs_for_ast_path(
+ let (generic_args, arg_count) = self.create_args_for_ast_path(
trait_ref_span,
trait_def_id,
&[],
@@ -704,11 +707,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
- let poly_trait_ref =
- ty::Binder::bind_with_vars(ty::TraitRef::new(tcx, trait_def_id, substs), bound_vars);
+ let poly_trait_ref = ty::Binder::bind_with_vars(
+ ty::TraitRef::new(tcx, trait_def_id, generic_args),
+ bound_vars,
+ );
debug!(?poly_trait_ref, ?assoc_bindings);
- bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity);
+ bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {
@@ -844,9 +849,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
+ // FIXME(effects) move all host param things in astconv to hir lowering
constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
- let (substs, _) = self.create_substs_for_ast_trait_ref(
+ let (generic_args, _) = self.create_args_for_ast_trait_ref(
span,
trait_def_id,
self_ty,
@@ -857,11 +863,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(b) = trait_segment.args().bindings.first() {
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
}
- ty::TraitRef::new(self.tcx(), trait_def_id, substs)
+ ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
}
#[instrument(level = "debug", skip(self, span))]
- fn create_substs_for_ast_trait_ref<'a>(
+ fn create_args_for_ast_trait_ref<'a>(
&self,
span: Span,
trait_def_id: DefId,
@@ -869,10 +875,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_segment: &'a hir::PathSegment<'a>,
is_impl: bool,
constness: ty::BoundConstness,
- ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
+ ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) {
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
- self.create_substs_for_ast_path(
+ self.create_args_for_ast_path(
span,
trait_def_id,
&[],
@@ -902,19 +908,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
did: DefId,
item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> {
- let substs = self.ast_path_substs_for_ty(span, did, item_segment);
- let ty = self.tcx().at(span).type_of(did);
+ let tcx = self.tcx();
+ let args = self.ast_path_args_for_ty(span, did, item_segment);
+ let ty = tcx.at(span).type_of(did);
- if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
- && (ty.skip_binder().has_opaque_types() || self.tcx().features().lazy_type_alias)
+ if let DefKind::TyAlias { lazy } = tcx.def_kind(did)
+ && (lazy || ty.skip_binder().has_opaque_types())
{
// Type aliases referring to types that contain opaque types (but aren't just directly
- // referencing a single opaque type) get encoded as a type alias that normalization will
+ // referencing a single opaque type) as well as those defined in crates that have the
+ // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
// then actually instantiate the where bounds of.
- let alias_ty = self.tcx().mk_alias_ty(did, substs);
- Ty::new_alias(self.tcx(), ty::Weak, alias_ty)
+ let alias_ty = tcx.mk_alias_ty(did, args);
+ Ty::new_alias(tcx, ty::Weak, alias_ty)
} else {
- ty.subst(self.tcx(), substs)
+ ty.instantiate(tcx, args)
}
}
@@ -1123,7 +1131,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty_param_name
)
};
- err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
+ err.span_label(span, format!("ambiguous associated type `{assoc_name}`"));
let mut where_bounds = vec![];
for bound in bounds {
@@ -1267,9 +1275,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"you might have meant to specify type parameters on enum \
`{type_name}`"
);
- let Some(args) = assoc_segment.args else { return; };
+ let Some(args) = assoc_segment.args else {
+ return;
+ };
// Get the span of the generics args *including* the leading `::`.
- let args_span = assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
+ let args_span =
+ assoc_segment.ident.span.shrink_to_hi().to(args.span_ext);
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*.
@@ -1281,49 +1292,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
);
return;
}
- let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
+ let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span)
+ else {
err.note(msg);
return;
};
- let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
- hir::QPath::Resolved(_, path)
- ) = &qself.kind {
- // If the path segment already has type params, we want to overwrite
- // them.
- match &path.segments {
- // `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,
- res: Res::Def(DefKind::Enum, _),
- ..
- }, _] => (
- // 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(),
- |a| a.span_ext)),
- false,
- ),
- [segment] => (
- // We need to include the `::` in `Type::Variant::<Args>`
- // to point the span to `::<Args>`, not just `<Args>`.
- 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,
- ),
- _ => {
- err.note(msg);
- return;
+ let (qself_sugg_span, is_self) =
+ if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) =
+ &qself.kind
+ {
+ // If the path segment already has type params, we want to overwrite
+ // them.
+ match &path.segments {
+ // `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,
+ res: Res::Def(DefKind::Enum, _),
+ ..
+ },
+ _,
+ ] => (
+ // 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(), |a| a.span_ext)),
+ false,
+ ),
+ [segment] => (
+ // We need to include the `::` in `Type::Variant::<Args>`
+ // to point the span to `::<Args>`, not just `<Args>`.
+ 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,
+ ),
+ _ => {
+ err.note(msg);
+ return;
+ }
}
- }
- } else {
- err.note(msg);
- return;
- };
+ } else {
+ err.note(msg);
+ return;
+ };
let suggestion = vec![
if is_self {
// Account for people writing `Self::Variant::<Args>`, where
@@ -1373,7 +1391,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
self.one_bound_for_assoc_type(
- || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
+ || {
+ traits::supertraits(
+ tcx,
+ ty::Binder::dummy(trait_ref.instantiate_identity()),
+ )
+ },
kw::SelfUpper,
assoc_ident,
span,
@@ -1387,7 +1410,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
_ => {
let reported = if variant_resolution.is_some() {
// Variant in type position
- let msg = format!("expected type, found variant `{}`", assoc_ident);
+ let msg = format!("expected type, found variant `{assoc_ident}`");
tcx.sess.span_err(span, msg)
} else if qself_ty.is_enum() {
let mut err = struct_span_err!(
@@ -1418,12 +1441,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} else {
err.span_label(
assoc_ident.span,
- format!("variant not found in `{}`", qself_ty),
+ format!("variant not found in `{qself_ty}`"),
);
}
if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
- err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
+ err.span_label(sp, format!("variant `{assoc_ident}` not found here"));
}
err.emit()
@@ -1442,7 +1465,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let traits: Vec<_> =
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
- // Don't print `TyErr` to the user.
+ // Don't print `ty::Error` to the user.
self.report_ambiguous_associated_type(
span,
&[qself_ty.to_string()],
@@ -1455,7 +1478,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
let trait_did = bound.def_id();
- let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) else {
+ 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.
let msg = format!("found associated const `{assoc_ident}` when type was expected");
@@ -1609,8 +1633,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligations(obligations.clone());
- let impl_substs = infcx.fresh_substs_for_item(span, impl_);
- let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs);
+ let impl_args = infcx.fresh_args_for_item(span, impl_);
+ let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
// Check that the self types can be related.
@@ -1622,7 +1646,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// Check whether the impl imposes obligations we have to worry about.
- let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_substs);
+ let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
let impl_obligations = traits::predicates_for_generics(
|_, _| cause.clone(),
@@ -1654,18 +1678,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
- // FIXME(fmease): Currently creating throwaway `parent_substs` to please
- // `create_substs_for_associated_item`. Modify the latter instead (or sth. similar) to
- // not require the parent substs logic.
- let parent_substs = InternalSubsts::identity_for_item(tcx, impl_);
- let substs =
- self.create_substs_for_associated_item(span, assoc_item, segment, parent_substs);
- let substs = tcx.mk_substs_from_iter(
+ // FIXME(fmease): Currently creating throwaway `parent_args` to please
+ // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
+ // not require the parent args logic.
+ let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
+ let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
+ let args = tcx.mk_args_from_iter(
std::iter::once(ty::GenericArg::from(self_ty))
- .chain(substs.into_iter().skip(parent_substs.len())),
+ .chain(args.into_iter().skip(parent_args.len())),
);
- let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, substs));
+ let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, args));
return Ok(Some((ty, assoc_item)));
}
@@ -1769,9 +1792,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
trait_ref.is_some_and(|trait_ref| {
- let impl_ = trait_ref.subst(
+ let impl_ = trait_ref.instantiate(
tcx,
- infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
+ infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
);
let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here...
@@ -1814,7 +1837,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
- let parent_def_id = def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+ let parent_def_id = def_id
+ .as_local()
+ .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
.map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
@@ -1835,7 +1860,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
- .map(|impl_| impl_.subst_identity().self_ty())
+ .map(|impl_| impl_.instantiate_identity().self_ty())
// We don't care about blanket impls.
.filter(|self_ty| !self_ty.has_non_region_param())
.map(|self_ty| tcx.erase_regions(self_ty).to_string())
@@ -1850,7 +1875,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&[path_str],
item_segment.ident.name,
);
- return Ty::new_error(tcx,reported)
+ return Ty::new_error(tcx, reported);
};
debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -1864,16 +1889,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
constness,
);
- let item_substs = self.create_substs_for_associated_item(
- span,
- item_def_id,
- item_segment,
- trait_ref.substs,
- );
+ let item_args =
+ self.create_args_for_associated_item(span, item_def_id, item_segment, trait_ref.args);
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
- Ty::new_projection(tcx, item_def_id, item_substs)
+ Ty::new_projection(tcx, item_def_id, item_args)
}
pub fn prohibit_generics<'a>(
@@ -2128,19 +2149,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let span = path.span;
match path.res {
- Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
+ Res::Def(DefKind::OpaqueTy, did) => {
// Check for desugared `impl Trait`.
assert!(tcx.is_type_alias_impl_trait(did));
let item_segment = path.segments.split_last().unwrap();
self.prohibit_generics(item_segment.1.iter(), |err| {
err.note("`impl Trait` types can't have type parameters");
});
- let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
- Ty::new_opaque(tcx, did, substs)
+ let args = self.ast_path_args_for_ty(span, did, item_segment.0);
+ Ty::new_opaque(tcx, did, args)
}
Res::Def(
DefKind::Enum
- | DefKind::TyAlias
+ | DefKind::TyAlias { .. }
| DefKind::Struct
| DefKind::Union
| DefKind::ForeignTy,
@@ -2220,7 +2241,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// `Self` in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
// Try to evaluate any array length constants.
- let ty = tcx.at(span).type_of(def_id).subst_identity();
+ let ty = tcx.at(span).type_of(def_id).instantiate_identity();
let span_of_impl = tcx.span_of_impl(def_id);
self.prohibit_generics(path.segments.iter(), |err| {
let def_id = match *ty.kind() {
@@ -2439,7 +2460,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
// generate the def_id of an associated type for the trait and return as
// type a projection.
- let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+ let def_id = if in_trait {
tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id()
} else {
local_def_id.to_def_id()
@@ -2458,7 +2479,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
&hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
let def_id = tcx.require_lang_item(lang_item, Some(span));
- let (substs, _) = self.create_substs_for_ast_path(
+ let (args, _) = self.create_args_for_ast_path(
span,
def_id,
&[],
@@ -2468,7 +2489,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
None,
ty::BoundConstness::NotConst,
);
- tcx.at(span).type_of(def_id).subst(tcx, substs)
+ tcx.at(span).type_of(def_id).instantiate(tcx, args)
}
hir::TyKind::Array(ty, length) => {
let length = match length {
@@ -2481,7 +2502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length)
}
hir::TyKind::Typeof(e) => {
- let ty_erased = tcx.type_of(e.def_id).subst_identity();
+ let ty_erased = tcx.type_of(e.def_id).instantiate_identity();
let ty = tcx.fold_regions(ty_erased, |r, _| {
if r.is_erased() { tcx.lifetimes.re_static } else { r }
});
@@ -2523,7 +2544,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let generics = tcx.generics_of(def_id);
debug!("impl_trait_ty_to_ty: generics={:?}", generics);
- let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
+ let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
// We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
// since return-position impl trait in trait squashes all of the generics from its source fn
// into its own generics, so the opaque's "own" params isn't always just lifetimes.
@@ -2537,12 +2558,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_param_from_def(param)
}
});
- debug!("impl_trait_ty_to_ty: substs={:?}", substs);
+ debug!("impl_trait_ty_to_ty: args={:?}", args);
if in_trait {
- Ty::new_projection(tcx, def_id, substs)
+ Ty::new_projection(tcx, def_id, args)
} else {
- Ty::new_opaque(tcx, def_id, substs)
+ Ty::new_opaque(tcx, def_id, args)
}
}
@@ -2688,14 +2709,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let hir = tcx.hir();
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
- hir.get(fn_hir_id) else { return None };
+ hir.get(fn_hir_id)
+ else {
+ return None;
+ };
let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
- let trait_ref = self.instantiate_mono_trait_ref(
- i.of_trait.as_ref()?,
- self.ast_ty_to_ty(i.self_ty),
- ty::BoundConstness::NotConst,
- );
+ let trait_ref =
+ self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
tcx,
@@ -2704,9 +2725,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref.def_id,
)?;
- let fn_sig = tcx.fn_sig(assoc.def_id).subst(
+ let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(
tcx,
- trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
+ trait_ref.args.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
);
let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
@@ -2729,7 +2750,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
"an anonymous lifetime".to_string()
}
- ty::BrNamed(_, name) => format!("lifetime `{}`", name),
+ ty::BrNamed(_, name) => format!("lifetime `{name}`"),
};
let mut err = generate_err(&br_name);
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 9227ee934..30c2ab8f5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -62,11 +62,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
match bound_pred.skip_binder() {
ty::ClauseKind::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,
- ));
+ trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
}
ty::ClauseKind::Projection(proj) => {
projection_bounds.push((bound_pred.rebind(proj), span));
@@ -86,7 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Expand trait aliases recursively and check that only one regular (non-auto) trait
// is used and no 'maybe' bounds are used.
let expanded_traits =
- traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+ traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
@@ -126,7 +122,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if regular_traits.is_empty() && auto_traits.is_empty() {
let trait_alias_span = trait_bounds
.iter()
- .map(|&(trait_ref, _, _)| trait_ref.def_id())
+ .map(|&(trait_ref, _)| trait_ref.def_id())
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
.map(|trait_ref| tcx.def_span(trait_ref));
let reported =
@@ -157,10 +153,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let regular_traits_refs_spans = trait_bounds
.into_iter()
- .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
+ .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
- for (base_trait_ref, span, constness) in regular_traits_refs_spans {
- assert_eq!(constness, ty::BoundConstness::NotConst);
+ for (base_trait_ref, span) in regular_traits_refs_spans {
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
for pred in traits::elaborate(tcx, [base_pred]) {
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
@@ -173,7 +168,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.associated_items(pred.def_id())
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
- .filter(|item| item.opt_rpitit_info.is_none())
+ .filter(|item| !item.is_impl_trait_in_trait())
.map(|item| item.def_id),
);
}
@@ -262,8 +257,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut missing_type_params = vec![];
let mut references_self = false;
let generics = tcx.generics_of(trait_ref.def_id);
- let substs: Vec<_> = trait_ref
- .substs
+ let args: Vec<_> = trait_ref
+ .args
.iter()
.enumerate()
.skip(1) // Remove `Self` for `ExistentialPredicate`.
@@ -279,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
arg
})
.collect();
- let substs = tcx.mk_substs(&substs);
+ let args = tcx.mk_args(&args);
let span = i.bottom().1;
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
@@ -310,7 +305,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.emit();
}
- ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
+ ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
})
});
@@ -325,7 +320,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// 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| {
+ let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
if arg.walk().any(|arg| arg == dummy_self.into()) {
return true;
}
@@ -336,9 +331,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
"trait object projection bounds reference `Self`",
);
- let substs: Vec<_> = b
+ let args: Vec<_> = b
.projection_ty
- .substs
+ .args
.iter()
.map(|arg| {
if arg.walk().any(|arg| arg == dummy_self.into()) {
@@ -347,7 +342,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
arg
})
.collect();
- b.projection_ty.substs = tcx.mk_substs(&substs);
+ b.projection_ty.args = tcx.mk_args(&args);
}
ty::ExistentialProjection::erase_self_ty(tcx, b)
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index c07ac35cb..39db29504 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
- && let ty::Alias(ty::Projection, _) = ty.kind()
+ && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
self.state.obligations.extend(obligations);
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 531100e1f..1d9ae2b9c 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -42,13 +42,12 @@ impl<'tcx> Bounds<'tcx> {
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
- constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) {
self.clauses.push((
trait_ref
.map_bound(|trait_ref| {
- ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
+ ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
})
.to_predicate(tcx),
span,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 120545c8e..2c7788498 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -8,7 +8,7 @@ use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
@@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
- self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
@@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
+use rustc_type_ir::fold::TypeFoldable;
use std::ops::ControlFlow;
@@ -96,8 +99,8 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Check that the fields of the `union` do not need dropping.
fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
- let item_type = tcx.type_of(item_def_id).subst_identity();
- if let ty::Adt(def, substs) = item_type.kind() {
+ let item_type = tcx.type_of(item_def_id).instantiate_identity();
+ if let ty::Adt(def, args) = item_type.kind() {
assert!(def.is_union());
fn allowed_union_field<'tcx>(
@@ -128,7 +131,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
let param_env = tcx.param_env(item_def_id);
for field in &def.non_enum_variant().fields {
- let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, substs));
+ let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, args));
if !allowed_union_field(field_ty, tcx, param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
@@ -163,7 +166,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// would be enough to check this for `extern` statics, as statics with an initializer will
// have UB during initialization if they are uninhabited, but there also seems to be no good
// reason to allow any statics to be uninhabited.
- let ty = tcx.type_of(def_id).subst_identity();
+ let ty = tcx.type_of(def_id).instantiate_identity();
let span = tcx.def_span(def_id);
let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
Ok(l) => l,
@@ -212,16 +215,16 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
}
- let substs = InternalSubsts::identity_for_item(tcx, item.owner_id);
+ let args = GenericArgs::identity_for_item(tcx, item.owner_id);
let span = tcx.def_span(item.owner_id.def_id);
if !tcx.features().impl_trait_projections {
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
}
- if tcx.type_of(item.owner_id.def_id).subst_identity().references_error() {
+ if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
return;
}
- if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
+ if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() {
return;
}
@@ -302,16 +305,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
if let ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
- in_trait,
..
}) = item.kind
{
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
- Ty::new_projection(tcx, def_id.to_def_id(), substs)
- } else {
- Ty::new_opaque(tcx, def_id.to_def_id(), substs)
- };
+ let args = GenericArgs::identity_for_item(tcx, def_id);
+ let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
let mut visitor = ProhibitOpaqueVisitor {
opaque_identity_ty,
parent_count: tcx.generics_of(def_id).parent_count as u32,
@@ -321,7 +319,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
};
let prohibit_opaque = tcx
.explicit_item_bounds(def_id)
- .subst_identity_iter_copied()
+ .instantiate_identity_iter_copied()
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
if let Some(ty) = prohibit_opaque.break_value() {
@@ -347,7 +345,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
err.span_suggestion(
span,
"consider spelling out the type instead",
- name.unwrap_or_else(|| format!("{:?}", ty)),
+ name.unwrap_or_else(|| format!("{ty:?}")),
Applicability::MaybeIncorrect,
);
}
@@ -360,11 +358,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
pub(super) fn check_opaque_for_cycles<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
span: Span,
origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> {
- if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
+ if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
let reported = match origin {
hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
_ => opaque_type_cycle_error(tcx, def_id, span),
@@ -409,16 +407,26 @@ fn check_opaque_meets_bounds<'tcx>(
.build();
let ocx = ObligationCtxt::new(&infcx);
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
+ let args = match *origin {
+ hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
+ GenericArgs::identity_for_item(tcx, parent).extend_to(
+ tcx,
+ def_id.to_def_id(),
+ |param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(),
+ )
+ }
+ hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id),
+ };
+
+ let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
- // `ReErased` regions appear in the "parent_substs" of closures/generators.
+ // `ReErased` regions appear in the "parent_args" of closures/generators.
// We're ignoring them here and replacing them with fresh region variables.
- // See tests in ui/type-alias-impl-trait/closure_{parent_substs,wf_outlives}.rs.
+ // See tests in ui/type-alias-impl-trait/closure_{parent_args,wf_outlives}.rs.
//
// FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
// here rather than using ReErased.
- let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
+ let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
_ => re,
@@ -442,7 +450,7 @@ fn check_opaque_meets_bounds<'tcx>(
// hidden type is well formed even without those bounds.
let predicate =
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
- ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
+ ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate));
// Check that all obligations are satisfied by the implementation's
// version.
@@ -453,7 +461,15 @@ fn check_opaque_meets_bounds<'tcx>(
}
match origin {
// Checked when type checking the function containing them.
- hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+ hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
+ // HACK: this should also fall through to the hidden type check below, but the original
+ // implementation had a bug where equivalent lifetimes are not identical. This caused us
+ // to reject existing stable code that is otherwise completely fine. The real fix is to
+ // compare the hidden types via our type equivalence/relation infra instead of doing an
+ // identity check.
+ let _ = infcx.take_opaque_types();
+ return Ok(());
+ }
// Nested opaque types occur only in associated types:
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
// They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
@@ -469,15 +485,63 @@ fn check_opaque_meets_bounds<'tcx>(
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
}
}
- // Clean up after ourselves
- let _ = infcx.take_opaque_types();
+ // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
+ for (mut key, mut ty) in infcx.take_opaque_types() {
+ ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
+ key = infcx.resolve_vars_if_possible(key);
+ sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
+ }
Ok(())
}
+fn sanity_check_found_hidden_type<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ key: ty::OpaqueTypeKey<'tcx>,
+ mut ty: ty::OpaqueHiddenType<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+ if ty.ty.is_ty_var() {
+ // Nothing was actually constrained.
+ return Ok(());
+ }
+ if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
+ if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
+ // Nothing was actually constrained, this is an opaque usage that was
+ // only discovered to be opaque after inference vars resolved.
+ return Ok(());
+ }
+ }
+ let strip_vars = |ty: Ty<'tcx>| {
+ ty.fold_with(&mut BottomUpFolder {
+ tcx,
+ ty_op: |t| t,
+ ct_op: |c| c,
+ lt_op: |l| match l.kind() {
+ RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
+ _ => l,
+ },
+ })
+ };
+ // Closures frequently end up containing erased lifetimes in their final representation.
+ // These correspond to lifetime variables that never got resolved, so we patch this up here.
+ ty.ty = strip_vars(ty.ty);
+ // Get the hidden type.
+ let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
+ let hidden_ty = strip_vars(hidden_ty);
+
+ // If the hidden types differ, emit a type mismatch diagnostic.
+ if hidden_ty == ty.ty {
+ Ok(())
+ } else {
+ let span = tcx.def_span(key.def_id);
+ let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
+ Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
+ }
+}
+
fn is_enum_of_nonnullable_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
adt_def: AdtDef<'tcx>,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
) -> bool {
if adt_def.repr().inhibit_enum_layout_opt() {
return false;
@@ -489,14 +553,14 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
return false;
};
- matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+ matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
}
fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
- if match tcx.type_of(def_id).subst_identity().kind() {
+ if match tcx.type_of(def_id).instantiate_identity().kind() {
ty::RawPtr(_) => false,
- ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+ ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
_ => true,
} {
tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
@@ -530,7 +594,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_impl_items_against_trait(
tcx,
id.owner_id.def_id,
- impl_trait_ref.subst_identity(),
+ impl_trait_ref.instantiate_identity(),
);
check_on_unimplemented(tcx, id);
}
@@ -546,13 +610,13 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
}
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
- let trait_substs =
- InternalSubsts::identity_for_item(tcx, id.owner_id);
+ let trait_args =
+ GenericArgs::identity_for_item(tcx, id.owner_id);
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
- ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_substs),
+ ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_args),
);
}
_ => {}
@@ -576,19 +640,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_opaque(tcx, id);
}
}
- DefKind::ImplTraitPlaceholder => {
- let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
- // Only check the validity of this opaque type if the function has a default body
- if let hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
- ..
- }) = tcx.hir().get_by_def_id(parent.expect_local())
- {
- check_opaque(tcx, id);
- }
- }
- DefKind::TyAlias => {
- let pty_ty = tcx.type_of(id.owner_id).subst_identity();
+ DefKind::TyAlias { .. } => {
+ let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
let generics = tcx.generics_of(id.owner_id);
check_type_params_are_used(tcx, &generics, pty_ty);
}
@@ -642,7 +695,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
"replace the {} parameters with concrete {}{}",
kinds,
kinds_pl,
- egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
+ egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
),
)
.emit();
@@ -727,7 +780,7 @@ pub(super) fn check_specialization_validity<'tcx>(
} else {
tcx.sess.delay_span_bug(
DUMMY_SP,
- format!("parent item: {:?} not marked as default", parent_impl),
+ format!("parent item: {parent_impl:?} not marked as default"),
);
}
}
@@ -902,8 +955,8 @@ fn check_impl_items_against_trait<'tcx>(
}
pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
- let t = tcx.type_of(def_id).subst_identity();
- if let ty::Adt(def, substs) = t.kind()
+ let t = tcx.type_of(def_id).instantiate_identity();
+ if let ty::Adt(def, args) = t.kind()
&& def.is_struct()
{
let fields = &def.non_enum_variant().fields;
@@ -911,8 +964,8 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
- let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
- if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
+ let e = fields[FieldIdx::from_u32(0)].ty(tcx, args);
+ if !fields.iter().all(|f| f.ty(tcx, args) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
.emit();
@@ -1019,7 +1072,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
if first {
format!(
"`{}` contains a field of type `{}`",
- tcx.type_of(def.did()).subst_identity(),
+ tcx.type_of(def.did()).instantiate_identity(),
ident
)
} else {
@@ -1041,7 +1094,7 @@ pub(super) fn check_packed_inner(
def_id: DefId,
stack: &mut Vec<DefId>,
) -> Option<Vec<(DefId, Span)>> {
- if let ty::Adt(def, substs) = tcx.type_of(def_id).subst_identity().kind() {
+ if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().kind() {
if def.is_struct() || def.is_union() {
if def.repr().align.is_some() {
return Some(vec![(def.did(), DUMMY_SP)]);
@@ -1049,7 +1102,7 @@ pub(super) fn check_packed_inner(
stack.push(def_id);
for field in &def.non_enum_variant().fields {
- if let ty::Adt(def, _) = field.ty(tcx, substs).kind()
+ if let ty::Adt(def, _) = field.ty(tcx, args).kind()
&& !stack.contains(&def.did())
&& let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
{
@@ -1088,21 +1141,21 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// For each field, figure out if it's known to be a ZST and align(1), with "known"
// respecting #[non_exhaustive] attributes.
let field_infos = adt.all_fields().map(|field| {
- let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
+ let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
let zst = layout.is_ok_and(|layout| layout.is_zst());
- let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
+ let align = layout.ok().map(|layout| layout.align.abi.bytes());
if !zst {
- return (span, zst, align1, None);
+ return (span, zst, align, None);
}
fn check_non_exhaustive<'tcx>(
tcx: TyCtxt<'tcx>,
t: Ty<'tcx>,
- ) -> ControlFlow<(&'static str, DefId, SubstsRef<'tcx>, bool)> {
+ ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> {
match t.kind() {
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
@@ -1131,12 +1184,12 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
}
}
- (span, zst, align1, check_non_exhaustive(tcx, ty).break_value())
+ (span, zst, align, check_non_exhaustive(tcx, ty).break_value())
});
let non_zst_fields = field_infos
.clone()
- .filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
+ .filter_map(|(span, zst, _align, _non_exhaustive)| if !zst { Some(span) } else { None });
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count >= 2 {
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
@@ -1144,19 +1197,28 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
let incompatible_zst_fields =
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
let incompat = incompatible_zst_fields + non_zst_count >= 2 && non_zst_count < 2;
- for (span, zst, align1, non_exhaustive) in field_infos {
- if zst && !align1 {
- struct_span_err!(
+ for (span, zst, align, non_exhaustive) in field_infos {
+ if zst && align != Some(1) {
+ let mut err = struct_span_err!(
tcx.sess,
span,
E0691,
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr(),
- )
- .span_label(span, "has alignment larger than 1")
- .emit();
+ );
+
+ if let Some(align_bytes) = align {
+ err.span_label(
+ span,
+ format!("has alignment of {align_bytes}, which is larger than 1"),
+ );
+ } else {
+ err.span_label(span, "may have alignment larger than 1");
+ }
+
+ err.emit();
}
- if incompat && let Some((descr, def_id, substs, non_exhaustive)) = non_exhaustive {
+ if incompat && let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
@@ -1168,7 +1230,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
} else {
"contains private fields"
};
- let field_ty = tcx.def_path_str_with_substs(def_id, substs);
+ let field_ty = tcx.def_path_str_with_args(def_id, args);
lint
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become non-zero-sized in the future."))
@@ -1389,11 +1451,14 @@ pub(super) fn check_type_params_are_used<'tcx>(
}
}
-pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
+pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
check_item_type(tcx, id);
}
+ if module_def_id == LocalModDefId::CRATE_DEF_ID {
+ super::entry::check_for_entry_fn(tcx);
+ }
}
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 22e576e34..bd0ab6463 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1,7 +1,7 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::{DefId, LocalDefId};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{
pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
};
@@ -16,7 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
- self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+ self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::{Span, DUMMY_SP};
@@ -76,7 +76,7 @@ fn check_method_is_structurally_compatible<'tcx>(
Ok(())
}
-/// This function is best explained by example. Consider a trait with it's implementation:
+/// This function is best explained by example. Consider a trait with its implementation:
///
/// ```rust
/// trait Trait<'t, T> {
@@ -96,15 +96,15 @@ fn check_method_is_structurally_compatible<'tcx>(
/// For this we have to show that, assuming the bounds of the impl hold, the
/// bounds of `trait_m` imply the bounds of `impl_m`.
///
-/// We start out with `trait_to_impl_substs`, that maps the trait
+/// We start out with `trait_to_impl_args`, that maps the trait
/// type parameters to impl type parameters. This is taken from the
/// impl trait reference:
///
/// ```rust,ignore (pseudo-Rust)
-/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+/// trait_to_impl_args = {'t => 'j, T => &'i U, Self => Foo}
/// ```
///
-/// We create a mapping `dummy_substs` that maps from the impl type
+/// We create a mapping `dummy_args` that maps from the impl type
/// parameters to fresh types and regions. For type parameters,
/// this is the identity transform, but we could as well use any
/// placeholder types. For regions, we convert from bound to free
@@ -112,32 +112,32 @@ fn check_method_is_structurally_compatible<'tcx>(
/// declared on the impl or used in type parameter bounds).
///
/// ```rust,ignore (pseudo-Rust)
-/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+/// impl_to_placeholder_args = {'i => 'i0, U => U0, N => N0 }
/// ```
///
-/// Now we can apply `placeholder_substs` to the type of the impl method
+/// Now we can apply `placeholder_args` to the type of the impl method
/// to yield a new function type in terms of our fresh, placeholder
/// types:
///
/// ```rust,ignore (pseudo-Rust)
-/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
/// ```
///
/// We now want to extract and substitute the type of the *trait*
/// method and compare it. To do so, we must create a compound
-/// substitution by combining `trait_to_impl_substs` and
-/// `impl_to_placeholder_substs`, and also adding a mapping for the method
+/// substitution by combining `trait_to_impl_args` and
+/// `impl_to_placeholder_args`, and also adding a mapping for the method
/// type parameters. We extend the mapping to also include
/// the method parameters.
///
/// ```rust,ignore (pseudo-Rust)
-/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+/// trait_to_placeholder_args = { T => &'i0 U0, Self => Foo, M => N0 }
/// ```
///
/// Applying this to the trait method type yields:
///
/// ```rust,ignore (pseudo-Rust)
-/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+/// <'a> fn(t: &'i0 U0, m: &'a N0) -> Foo
/// ```
///
/// This type is also the same but the name of the bound region (`'a`
@@ -148,8 +148,8 @@ fn check_method_is_structurally_compatible<'tcx>(
/// satisfied by the implementation's method.
///
/// We do this by creating a parameter environment which contains a
-/// substitution corresponding to `impl_to_placeholder_substs`. We then build
-/// `trait_to_placeholder_substs` and use it to convert the predicates contained
+/// substitution corresponding to `impl_to_placeholder_args`. We then build
+/// `trait_to_placeholder_args` and use it to convert the predicates contained
/// in the `trait_m` generics to the placeholder form.
///
/// Finally we register each of these predicates as an obligation and check that
@@ -162,7 +162,7 @@ fn compare_method_predicate_entailment<'tcx>(
impl_trait_ref: ty::TraitRef<'tcx>,
check_implied_wf: CheckImpliedWfMode,
) -> Result<(), ErrorGuaranteed> {
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let trait_to_impl_args = impl_trait_ref.args;
// This node-id should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`).
@@ -182,12 +182,12 @@ fn compare_method_predicate_entailment<'tcx>(
);
// Create mapping from impl to placeholder.
- let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+ let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to placeholder.
- let trait_to_placeholder_substs =
- impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
- debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
+ let trait_to_placeholder_args =
+ impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
+ debug!("compare_impl_method: trait_to_placeholder_args={:?}", trait_to_placeholder_args);
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
@@ -211,7 +211,7 @@ fn compare_method_predicate_entailment<'tcx>(
// if all constraints hold.
hybrid_preds.predicates.extend(
trait_m_predicates
- .instantiate_own(tcx, trait_to_placeholder_substs)
+ .instantiate_own(tcx, trait_to_placeholder_args)
.map(|(predicate, _)| predicate),
);
@@ -219,11 +219,7 @@ fn compare_method_predicate_entailment<'tcx>(
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
- let param_env = ty::ParamEnv::new(
- tcx.mk_clauses(&hybrid_preds.predicates),
- Reveal::UserFacing,
- hir::Constness::NotConst,
- );
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = &tcx.infer_ctxt().build();
@@ -231,7 +227,7 @@ fn compare_method_predicate_entailment<'tcx>(
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
- let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
+ let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_args);
for (predicate, span) in impl_m_own_bounds {
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
@@ -262,22 +258,19 @@ fn compare_method_predicate_entailment<'tcx>(
// type.
// Compute placeholder form of impl and trait method tys.
- let tcx = infcx.tcx;
-
let mut wf_tys = FxIndexSet::default();
let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
impl_m_span,
infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id).subst_identity(),
+ tcx.fn_sig(impl_m.def_id).instantiate_identity(),
);
- let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
debug!("compare_impl_method: impl_fty={:?}", impl_sig);
- let trait_sig = tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
+ let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
// Next, add all inputs and output as well-formed tys. Importantly,
@@ -315,16 +308,60 @@ fn compare_method_predicate_entailment<'tcx>(
}
if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
- // We need to check that the impl's args are well-formed given
- // the hybrid param-env (impl + trait method where-clauses).
- ocx.register_obligation(traits::Obligation::new(
- infcx.tcx,
- ObligationCause::dummy(),
- param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
- unnormalized_impl_fty.into(),
- ))),
- ));
+ // Select obligations to make progress on inference before processing
+ // the wf obligation below.
+ // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
+ let errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
+ return Err(reported);
+ }
+
+ // See #108544. Annoying, we can end up in cases where, because of winnowing,
+ // we pick param env candidates over a more general impl, leading to more
+ // stricter lifetime requirements than we would otherwise need. This can
+ // trigger the lint. Instead, let's only consider type outlives and
+ // region outlives obligations.
+ //
+ // FIXME(-Ztrait-solver=next): Try removing this hack again once
+ // the new solver is stable.
+ let mut wf_args: smallvec::SmallVec<[_; 4]> =
+ unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
+ // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
+ // will give back the well-formed predicate of the same array.
+ let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
+ while let Some(arg) = wf_args.pop() {
+ let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
+ infcx,
+ param_env,
+ impl_m_def_id,
+ 0,
+ arg,
+ impl_m_span,
+ ) else {
+ continue;
+ };
+ for obligation in obligations {
+ debug!(?obligation);
+ match obligation.predicate.kind().skip_binder() {
+ // We need to register Projection oblgiations too, because we may end up with
+ // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
+ // If we only register the region outlives obligation, this leads to an unconstrained var.
+ // See `implied_bounds_entailment_alias_var` test.
+ ty::PredicateKind::Clause(
+ ty::ClauseKind::RegionOutlives(..)
+ | ty::ClauseKind::TypeOutlives(..)
+ | ty::ClauseKind::Projection(..),
+ ) => ocx.register_obligation(obligation),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+ if wf_args_seen.insert(arg) {
+ wf_args.push(arg)
+ }
+ }
+ _ => {}
+ }
+ }
+ }
}
// Check that all obligations are satisfied by the implementation's
@@ -357,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>(
// lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
+ infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
);
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() {
@@ -615,14 +652,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
let impl_trait_ref =
- tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity();
+ tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
let param_env = tcx.param_env(impl_m_def_id);
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let trait_to_impl_args = impl_trait_ref.args;
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
@@ -637,11 +674,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
);
// Create mapping from impl to placeholder.
- let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
+ let impl_to_placeholder_args = GenericArgs::identity_for_item(tcx, impl_m.def_id);
// Create mapping from trait to placeholder.
- let trait_to_placeholder_substs =
- impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
+ let trait_to_placeholder_args =
+ impl_to_placeholder_args.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_args);
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
@@ -651,7 +688,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_sig = ocx.normalize(
&norm_cause,
param_env,
- tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
+ tcx.liberate_late_bound_regions(
+ impl_m.def_id,
+ tcx.fn_sig(impl_m.def_id).instantiate_identity(),
+ ),
);
impl_sig.error_reported()?;
let impl_return_ty = impl_sig.output();
@@ -665,7 +705,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
.instantiate_binder_with_fresh_vars(
return_span,
infer::HigherRankedType,
- tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
+ tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_placeholder_args),
)
.fold_with(&mut collector);
@@ -757,48 +797,48 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
);
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
- let mut collected_tys = FxHashMap::default();
- for (def_id, (ty, substs)) in collected_types {
- match infcx.fully_resolve((ty, substs)) {
- Ok((ty, substs)) => {
+ let mut remapped_types = FxHashMap::default();
+ for (def_id, (ty, args)) in collected_types {
+ match infcx.fully_resolve((ty, args)) {
+ Ok((ty, args)) => {
// `ty` contains free regions that we created earlier while liberating the
// trait fn signature. However, projection normalization expects `ty` to
// contains `def_id`'s early-bound regions.
- let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
- debug!(?id_substs, ?substs);
- let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
+ let id_args = GenericArgs::identity_for_item(tcx, def_id);
+ debug!(?id_args, ?args);
+ let map: FxHashMap<_, _> = std::iter::zip(args, id_args)
.skip(tcx.generics_of(trait_m.def_id).count())
.filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
.collect();
debug!(?map);
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
- // region substs that are synthesized during AST lowering. These are substs
- // that are appended to the parent substs (trait and trait method). However,
+ // region args that are synthesized during AST lowering. These are args
+ // that are appended to the parent args (trait and trait method). However,
// we're trying to infer the unsubstituted type value of the RPITIT inside
- // the *impl*, so we can later use the impl's method substs to normalize
+ // the *impl*, so we can later use the impl's method args to normalize
// an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
//
// Due to the design of RPITITs, during AST lowering, we have no idea that
// an impl method corresponds to a trait method with RPITITs in it. Therefore,
- // we don't have a list of early-bound region substs for the RPITIT in the impl.
+ // we don't have a list of early-bound region args for the RPITIT in the impl.
// Since early region parameters are index-based, we can't just rebase these
- // (trait method) early-bound region substs onto the impl, and there's no
- // guarantee that the indices from the trait substs and impl substs line up.
- // So to fix this, we subtract the number of trait substs and add the number of
- // impl substs to *renumber* these early-bound regions to their corresponding
+ // (trait method) early-bound region args onto the impl, and there's no
+ // guarantee that the indices from the trait args and impl args line up.
+ // So to fix this, we subtract the number of trait args and add the number of
+ // impl args to *renumber* these early-bound regions to their corresponding
// indices in the impl's substitutions list.
//
- // Also, we only need to account for a difference in trait and impl substs,
+ // Also, we only need to account for a difference in trait and impl args,
// since we previously enforce that the trait method and impl method have the
// same generics.
- let num_trait_substs = trait_to_impl_substs.len();
- let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
+ let num_trait_args = trait_to_impl_args.len();
+ let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).params.len();
let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
tcx,
map,
- num_trait_substs,
- num_impl_substs,
+ num_trait_args,
+ num_impl_args,
def_id,
impl_def_id: impl_m.container_id(tcx),
ty,
@@ -807,24 +847,42 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
Ok(ty) => ty,
Err(guar) => Ty::new_error(tcx, guar),
};
- collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
+ remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
+ remapped_types.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
}
}
}
- Ok(&*tcx.arena.alloc(collected_tys))
+ // We may not collect all RPITITs that we see in the HIR for a trait signature
+ // because an RPITIT was located within a missing item. Like if we have a sig
+ // returning `-> Missing<impl Sized>`, that gets converted to `-> [type error]`,
+ // and when walking through the signature we end up never collecting the def id
+ // of the `impl Sized`. Insert that here, so we don't ICE later.
+ for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
+ if !remapped_types.contains_key(assoc_item) {
+ remapped_types.insert(
+ *assoc_item,
+ ty::EarlyBinder::bind(Ty::new_error_with_message(
+ tcx,
+ return_span,
+ "missing synthetic item for RPITIT",
+ )),
+ );
+ }
+ }
+
+ Ok(&*tcx.arena.alloc(remapped_types))
}
struct ImplTraitInTraitCollector<'a, 'tcx> {
ocx: &'a ObligationCtxt<'a, 'tcx>,
- types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
+ types: FxHashMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId,
@@ -853,8 +911,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
}
- //FIXME(RPITIT): Deny nested RPITIT in substs too
- if proj.substs.has_escaping_bound_vars() {
+ //FIXME(RPITIT): Deny nested RPITIT in args too
+ if proj.args.has_escaping_bound_vars() {
bug!("FIXME(RPITIT): error here");
}
// Replace with infer var
@@ -862,9 +920,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
span: self.span,
kind: TypeVariableOriginKind::MiscVariable,
});
- self.types.insert(proj.def_id, (infer_ty, proj.substs));
+ self.types.insert(proj.def_id, (infer_ty, proj.args));
// Recurse into bounds
- for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
+ for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).iter_instantiated_copied(self.interner(), proj.args) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
@@ -893,8 +951,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
struct RemapHiddenTyRegions<'tcx> {
tcx: TyCtxt<'tcx>,
map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
- num_trait_substs: usize,
- num_impl_substs: usize,
+ num_trait_args: usize,
+ num_impl_args: usize,
def_id: DefId,
impl_def_id: DefId,
ty: Ty<'tcx>,
@@ -909,16 +967,16 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
}
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
- let mut mapped_substs = Vec::with_capacity(substs.len());
- for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
- mapped_substs.push(match (arg.unpack(), v) {
- // Skip uncaptured opaque substs
+ if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() {
+ let mut mapped_args = Vec::with_capacity(args.len());
+ for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) {
+ mapped_args.push(match (arg.unpack(), v) {
+ // Skip uncaptured opaque args
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
_ => arg.try_fold_with(self)?,
});
}
- Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_substs(&mapped_substs)))
+ Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args)))
} else {
t.try_super_fold_with(self)
}
@@ -975,7 +1033,7 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
ty::EarlyBoundRegion {
def_id: e.def_id,
name: e.name,
- index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
+ index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
},
))
}
@@ -1214,7 +1272,7 @@ fn compare_self_type<'tcx>(
ty::ImplContainer => impl_trait_ref.self_ty(),
ty::TraitContainer => tcx.types.self_param,
};
- let self_arg_ty = tcx.fn_sig(method.def_id).subst_identity().input(0);
+ let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let param_env = ty::ParamEnv::reveal_all();
let infcx = tcx.infer_ctxt().build();
@@ -1319,7 +1377,7 @@ fn compare_number_of_generics<'tcx>(
// has mismatched type or const generic arguments, then the method that it's
// inheriting the generics from will also have mismatched arguments, and
// we'll report an error for that instead. Delay a bug for safety, though.
- if trait_.opt_rpitit_info.is_some() {
+ if trait_.is_impl_trait_in_trait() {
return Err(tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
"errors comparing numbers of generics of trait/impl functions were not emitted",
@@ -1669,19 +1727,19 @@ fn compare_synthetic_generics<'tcx>(
/// ```rust,ignore (pseudo-Rust)
/// trait Foo {
/// fn foo<const N: u8>();
-/// type bar<const N: u8>;
+/// type Bar<const N: u8>;
/// fn baz<const N: u32>();
-/// type blah<T>;
+/// type Blah<T>;
/// }
///
/// impl Foo for () {
/// fn foo<const N: u64>() {}
/// //~^ error
-/// type bar<const N: u64> {}
+/// type Bar<const N: u64> = ();
/// //~^ error
/// fn baz<T>() {}
/// //~^ error
-/// type blah<const N: i64> = u32;
+/// type Blah<const N: i64> = u32;
/// //~^ error
/// }
/// ```
@@ -1738,10 +1796,10 @@ fn compare_generic_param_kinds<'tcx>(
format!(
"{} const parameter of type `{}`",
prefix,
- tcx.type_of(param.def_id).subst_identity()
+ tcx.type_of(param.def_id).instantiate_identity()
)
}
- Type { .. } => format!("{} type parameter", prefix),
+ Type { .. } => format!("{prefix} type parameter"),
Lifetime { .. } => unreachable!(),
};
@@ -1769,37 +1827,83 @@ pub(super) fn compare_impl_const_raw(
let impl_const_item = tcx.associated_item(impl_const_item_def);
let trait_const_item = tcx.associated_item(trait_const_item_def);
let impl_trait_ref =
- tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity();
- debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
+ tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
- let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
+ debug!("compare_impl_const(impl_trait_ref={:?})", impl_trait_ref);
- let infcx = tcx.infer_ctxt().build();
- let param_env = tcx.param_env(impl_const_item_def.to_def_id());
- let ocx = ObligationCtxt::new(&infcx);
+ compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
+ compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
+ compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
+}
+
+/// The equivalent of [compare_method_predicate_entailment], but for associated constants
+/// instead of associated functions.
+// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
+fn compare_const_predicate_entailment<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_ct: ty::AssocItem,
+ trait_ct: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+ let impl_ct_def_id = impl_ct.def_id.expect_local();
+ let impl_ct_span = tcx.def_span(impl_ct_def_id);
// The below is for the most part highly similar to the procedure
// for methods above. It is simpler in many respects, especially
// because we shouldn't really have to deal with lifetimes or
// predicates. In fact some of this should probably be put into
// shared functions because of DRY violations...
- let trait_to_impl_substs = impl_trait_ref.substs;
+ let impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id);
+ let trait_to_impl_args =
+ impl_args.rebase_onto(tcx, impl_ct.container_id(tcx), impl_trait_ref.args);
// Create a parameter environment that represents the implementation's
// method.
// Compute placeholder form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()).subst_identity();
- let trait_ty = tcx.type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
- let mut cause = ObligationCause::new(
- impl_c_span,
- impl_const_item_def,
- ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_const_item_def,
- trait_item_def_id: trait_const_item_def,
- kind: impl_const_item.kind,
- },
+ let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
+
+ let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
+ let code = ObligationCauseCode::CompareImplItemObligation {
+ impl_item_def_id: impl_ct_def_id,
+ trait_item_def_id: trait_ct.def_id,
+ kind: impl_ct.kind,
+ };
+ let mut cause = ObligationCause::new(impl_ct_span, impl_ct_def_id, code.clone());
+
+ let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
+ let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);
+
+ check_region_bounds_on_impl_item(tcx, impl_ct, trait_ct, false)?;
+
+ // The predicates declared by the impl definition, the trait and the
+ // associated const in the trait are assumed.
+ let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
+ let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
+ hybrid_preds.predicates.extend(
+ trait_ct_predicates
+ .instantiate_own(tcx, trait_to_impl_args)
+ .map(|(predicate, _)| predicate),
+ );
+
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
+ let param_env = traits::normalize_param_env_or_error(
+ tcx,
+ param_env,
+ ObligationCause::misc(impl_ct_span, impl_ct_def_id),
);
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
+
+ let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
+ for (predicate, span) in impl_ct_own_bounds {
+ let cause = ObligationCause::misc(span, impl_ct_def_id);
+ let predicate = ocx.normalize(&cause, param_env, predicate);
+
+ let cause = ObligationCause::new(span, impl_ct_def_id, code.clone());
+ ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
+ }
+
// There is no "body" here, so just pass dummy id.
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
@@ -1818,7 +1922,7 @@ pub(super) fn compare_impl_const_raw(
);
// Locate the Span containing just the type of the offending impl
- let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
+ let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
cause.span = ty.span;
let mut diag = struct_span_err!(
@@ -1826,12 +1930,12 @@ pub(super) fn compare_impl_const_raw(
cause.span,
E0326,
"implemented const `{}` has an incompatible type for trait",
- trait_const_item.name
+ trait_ct.name
);
- let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
+ let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
// Add a label to the Span containing just the type of the const
- let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
+ let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
ty.span
});
@@ -1858,7 +1962,7 @@ pub(super) fn compare_impl_const_raw(
}
let outlives_env = OutlivesEnvironment::new(param_env);
- ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
+ ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env)
}
pub(super) fn compare_impl_ty<'tcx>(
@@ -1885,26 +1989,26 @@ fn compare_type_predicate_entailment<'tcx>(
trait_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
- let trait_to_impl_substs =
- impl_substs.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.substs);
+ let impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+ let trait_to_impl_args =
+ impl_args.rebase_onto(tcx, impl_ty.container_id(tcx), impl_trait_ref.args);
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
- let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
+ let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
if impl_ty_own_bounds.len() == 0 {
// Nothing to check.
return Ok(());
}
- // This `HirId` should be used for the `body_id` field on each
+ // This `DefId` should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
let impl_ty_def_id = impl_ty.def_id.expect_local();
- debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
+ debug!("compare_type_predicate_entailment: trait_to_impl_args={:?}", trait_to_impl_args);
// The predicates declared by the impl definition, the trait and the
// associated type in the trait are assumed.
@@ -1912,19 +2016,15 @@ fn compare_type_predicate_entailment<'tcx>(
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
hybrid_preds.predicates.extend(
trait_ty_predicates
- .instantiate_own(tcx, trait_to_impl_substs)
+ .instantiate_own(tcx, trait_to_impl_args)
.map(|(predicate, _)| predicate),
);
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
let impl_ty_span = tcx.def_span(impl_ty_def_id);
- let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
- let param_env = ty::ParamEnv::new(
- tcx.mk_clauses(&hybrid_preds.predicates),
- Reveal::UserFacing,
- hir::Constness::NotConst,
- );
+ let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
+ let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@@ -1968,7 +2068,7 @@ fn compare_type_predicate_entailment<'tcx>(
///
/// trait X { type Y: Copy } impl X for T { type Y = S; }
///
-/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
+/// We are able to normalize `<T as X>::Y` to `S`, and so when we check the
/// impl is well-formed we have to prove `S: Copy`.
///
/// For default associated types the normalization is not possible (the value
@@ -1990,9 +2090,9 @@ pub(super) fn check_type_bounds<'tcx>(
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
- // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
- // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
+ // - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
// the *trait* with the generic associated type parameters (as bound vars).
//
// A note regarding the use of bound vars here:
@@ -2022,9 +2122,11 @@ pub(super) fn check_type_bounds<'tcx>(
// the trait (notably, that X: Eq and T: Family).
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
- // Extend the impl's identity substs with late-bound GAT vars
- let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id)
- .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
+ // Extend the impl's identity args with late-bound GAT vars
+ let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id).extend_to(
+ tcx,
+ impl_ty.def_id,
+ |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
@@ -2060,7 +2162,8 @@ pub(super) fn check_type_bounds<'tcx>(
)
.into()
}
- });
+ },
+ );
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
@@ -2070,15 +2173,14 @@ pub(super) fn check_type_bounds<'tcx>(
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
- let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs);
- let rebased_substs =
- normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let normalize_impl_ty = tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
+ let rebased_args = normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
- if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+ if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
{
// Don't include this predicate if the projected type is
// exactly the same as the projection. This can occur in
@@ -2089,7 +2191,7 @@ pub(super) fn check_type_bounds<'tcx>(
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
+ projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(),
},
bound_vars,
@@ -2097,13 +2199,13 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
- ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};
debug!(?normalize_param_env);
let impl_ty_def_id = impl_ty.def_id.expect_local();
- let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
- let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
+ let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@@ -2111,7 +2213,7 @@ pub(super) fn check_type_bounds<'tcx>(
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
// associated type.
- let impl_ty_span = if impl_ty.opt_rpitit_info.is_some() {
+ let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
tcx.def_span(impl_ty_def_id)
} else {
match tcx.hir().get_by_def_id(impl_ty_def_id) {
@@ -2144,7 +2246,7 @@ pub(super) fn check_type_bounds<'tcx>(
let obligations: Vec<_> = tcx
.explicit_item_bounds(trait_ty.def_id)
- .subst_iter_copied(tcx, rebased_substs)
+ .iter_instantiated_copied(tcx, rebased_args)
.map(|(concrete_ty_bound, span)| {
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 13d1abe2a..dda3f7425 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, ErrorGuaranteed};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::{self, ObligationCtxt};
@@ -44,21 +44,21 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
}));
}
}
- let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
+ let dtor_self_type = tcx.type_of(drop_impl_did).instantiate_identity();
match dtor_self_type.kind() {
- ty::Adt(adt_def, adt_to_impl_substs) => {
+ ty::Adt(adt_def, adt_to_impl_args) => {
ensure_drop_params_and_item_params_correspond(
tcx,
drop_impl_did.expect_local(),
adt_def.did(),
- adt_to_impl_substs,
+ adt_to_impl_args,
)?;
ensure_drop_predicates_are_implied_by_item_defn(
tcx,
drop_impl_did.expect_local(),
adt_def.did().expect_local(),
- adt_to_impl_substs,
+ adt_to_impl_args,
)
}
_ => {
@@ -79,10 +79,11 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_did: LocalDefId,
self_type_did: DefId,
- adt_to_impl_substs: SubstsRef<'tcx>,
+ adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
- return Ok(())
+ let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound)
+ else {
+ return Ok(());
};
let drop_impl_span = tcx.def_span(drop_impl_did);
@@ -114,12 +115,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_def_id: LocalDefId,
adt_def_id: LocalDefId,
- adt_to_impl_substs: SubstsRef<'tcx>,
+ adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
- // Take the param-env of the adt and substitute the substs that show up in
+ // Take the param-env of the adt and substitute the args that show up in
// the implementation's self type. This gives us the assumptions that the
// self ty of the implementation is allowed to know just from it being a
// well-formed adt, since that's all we're allowed to assume while proving
@@ -128,9 +129,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
- let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
- .subst(tcx, adt_to_impl_substs)
- .with_constness(tcx.constness(drop_impl_def_id));
+ let param_env =
+ ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
new file mode 100644
index 000000000..fcaefe026
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -0,0 +1,277 @@
+use rustc_hir as hir;
+use rustc_hir::Node;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::EntryFnType;
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_span::{symbol::sym, Span};
+use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+
+use std::ops::Not;
+
+use crate::errors;
+use crate::require_same_types;
+
+pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
+ match tcx.entry_fn(()) {
+ Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
+ Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
+ _ => {}
+ }
+}
+
+fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
+ let main_fnsig = tcx.fn_sig(main_def_id).instantiate_identity();
+ let main_span = tcx.def_span(main_def_id);
+
+ fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
+ if let Some(local_def_id) = def_id.as_local() {
+ let hir_type = tcx.type_of(local_def_id).instantiate_identity();
+ if !matches!(hir_type.kind(), ty::FnDef(..)) {
+ span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
+ }
+ local_def_id
+ } else {
+ CRATE_DEF_ID
+ }
+ }
+
+ fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
+ generics.params.is_empty().not().then_some(generics.span)
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
+ Some(generics.where_clause_span)
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ Some(tcx.def_span(def_id))
+ }
+
+ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
+ if !def_id.is_local() {
+ return None;
+ }
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ match tcx.hir().find(hir_id) {
+ Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
+ Some(fn_sig.decl.output.span())
+ }
+ _ => {
+ span_bug!(tcx.def_span(def_id), "main has a non-function type");
+ }
+ }
+ }
+
+ let mut error = false;
+ let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
+ let main_fn_generics = tcx.generics_of(main_def_id);
+ let main_fn_predicates = tcx.predicates_of(main_def_id);
+ if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
+ let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::MainFunctionGenericParameters {
+ span: generics_param_span.unwrap_or(main_span),
+ label_span: generics_param_span,
+ });
+ error = true;
+ } else if !main_fn_predicates.predicates.is_empty() {
+ // generics may bring in implicit predicates, so we skip this check if generics is present.
+ let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::WhereClauseOnMain {
+ span: generics_where_clauses_span.unwrap_or(main_span),
+ generics_span: generics_where_clauses_span,
+ });
+ error = true;
+ }
+
+ let main_asyncness = tcx.asyncness(main_def_id);
+ if let hir::IsAsync::Async = main_asyncness {
+ let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
+ tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
+ error = true;
+ }
+
+ for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
+ tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
+ error = true;
+ }
+
+ if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
+ // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
+ error = true;
+ }
+
+ if error {
+ return;
+ }
+
+ // Main should have no WC, so empty param env is OK here.
+ let param_env = ty::ParamEnv::empty();
+ let expected_return_type;
+ if let Some(term_did) = tcx.lang_items().termination() {
+ let return_ty = main_fnsig.output();
+ let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
+ if !return_ty.bound_vars().is_empty() {
+ tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
+ error = true;
+ }
+ let return_ty = return_ty.skip_binder();
+ let infcx = tcx.infer_ctxt().build();
+ let cause = traits::ObligationCause::new(
+ return_ty_span,
+ main_diagnostics_def_id,
+ ObligationCauseCode::MainFunctionType,
+ );
+ let ocx = traits::ObligationCtxt::new(&infcx);
+ let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
+ ocx.register_bound(cause, param_env, norm_return_ty, term_did);
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
+ error = true;
+ }
+ // now we can take the return type of the given main function
+ expected_return_type = main_fnsig.output();
+ } else {
+ // standard () main return type
+ expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
+ }
+
+ if error {
+ return;
+ }
+
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ expected_return_type.map_bound(|expected_return_type| {
+ tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
+ }),
+ );
+
+ require_same_types(
+ tcx,
+ &ObligationCause::new(
+ main_span,
+ main_diagnostics_def_id,
+ ObligationCauseCode::MainFunctionType,
+ ),
+ param_env,
+ se_ty,
+ Ty::new_fn_ptr(tcx, main_fnsig),
+ );
+}
+
+fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
+ let start_def_id = start_def_id.expect_local();
+ let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
+ let start_span = tcx.def_span(start_def_id);
+ let start_t = tcx.type_of(start_def_id).instantiate_identity();
+ match start_t.kind() {
+ ty::FnDef(..) => {
+ if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
+ if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
+ let mut error = false;
+ if !generics.params.is_empty() {
+ tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
+ error = true;
+ }
+ if generics.has_where_clause_predicates {
+ tcx.sess.emit_err(errors::StartFunctionWhere {
+ span: generics.where_clause_span,
+ });
+ error = true;
+ }
+ if let hir::IsAsync::Async = sig.header.asyncness {
+ let span = tcx.def_span(it.owner_id);
+ tcx.sess.emit_err(errors::StartAsync { span: span });
+ error = true;
+ }
+
+ let attrs = tcx.hir().attrs(start_id);
+ for attr in attrs {
+ if attr.has_name(sym::track_caller) {
+ tcx.sess.emit_err(errors::StartTrackCaller {
+ span: attr.span,
+ start: start_span,
+ });
+ error = true;
+ }
+ if attr.has_name(sym::target_feature)
+ // Calling functions with `#[target_feature]` is
+ // not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::StartTargetFeature {
+ span: attr.span,
+ start: start_span,
+ });
+ error = true;
+ }
+ }
+
+ if error {
+ return;
+ }
+ }
+ }
+
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ ty::Binder::dummy(tcx.mk_fn_sig(
+ [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+ tcx.types.isize,
+ false,
+ hir::Unsafety::Normal,
+ Abi::Rust,
+ )),
+ );
+
+ require_same_types(
+ tcx,
+ &ObligationCause::new(
+ start_span,
+ start_def_id,
+ ObligationCauseCode::StartFunctionType,
+ ),
+ ty::ParamEnv::empty(), // start should not have any where bounds.
+ se_ty,
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()),
+ );
+ }
+ _ => {
+ span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
+ }
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1248f991c..f89e2e5c2 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -60,7 +60,7 @@ fn equate_intrinsic_type<'tcx>(
tcx,
&cause,
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
- Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).subst_identity()),
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()),
fty,
);
}
@@ -134,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
- let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{}", n)));
+ let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{n}")));
let intrinsic_id = it.owner_id.to_def_id();
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
@@ -155,7 +155,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
);
- let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
+ let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
(Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
})
};
@@ -238,7 +238,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty: Ty::new_adt(
tcx,
tcx.adt_def(option_def_id),
- tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
+ tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()),
),
mutbl: hir::Mutability::Not,
},
@@ -273,6 +273,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
Ty::new_unit(tcx),
),
+ sym::compare_bytes => {
+ let byte_ptr = Ty::new_imm_ptr(tcx, tcx.types.u8);
+ (0, vec![byte_ptr, byte_ptr, tcx.types.usize], tcx.types.i32)
+ }
sym::write_bytes | sym::volatile_set_memory => (
1,
vec![
@@ -412,7 +416,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
param(0),
)],
- Ty::new_projection(tcx, discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
+ Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])),
)
}
@@ -494,7 +498,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
/// Type-check `extern "platform-intrinsic" { ... }` functions.
pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| {
- let name = Symbol::intern(&format!("P{}", n));
+ let name = Symbol::intern(&format!("P{n}"));
Ty::new_param(tcx, n, name)
};
@@ -521,6 +525,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
sym::simd_neg
+ | sym::simd_bswap
+ | sym::simd_bitreverse
+ | sym::simd_ctlz
+ | sym::simd_cttz
| sym::simd_fsqrt
| sym::simd_fsin
| sym::simd_fcos
@@ -563,20 +571,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_reduce_min_nanless
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
- name if name.as_str().starts_with("simd_shuffle") => {
- match name.as_str()["simd_shuffle".len()..].parse() {
- Ok(n) => {
- let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)];
- (2, params, param(1))
- }
- Err(_) => {
- let msg =
- format!("unrecognized platform-specific intrinsic function: `{name}`");
- tcx.sess.struct_span_err(it.span, msg).emit();
- return;
- }
- }
- }
_ => {
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
tcx.sess.struct_span_err(it.span, msg).emit();
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 0bb1467ef..945953edd 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -68,7 +68,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let asm_ty = match *ty.kind() {
// `!` is allowed for input but not for output (issue #87802)
ty::Never if is_input => return None,
- ty::Error(_) => return None,
+ _ if ty.references_error() => return None,
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
@@ -81,9 +81,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) if self.is_thin_ptr_ty(ty) => {
Some(asm_ty_isize)
}
- ty::Adt(adt, substs) if adt.repr().simd() => {
+ ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
- let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
+ let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args);
let (size, ty) = match elem_ty.kind() {
ty::Array(ty, len) => {
@@ -186,18 +186,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
- let supported_tys: Vec<_> =
- supported_tys.iter().map(|(t, _)| t.to_string()).collect();
+ let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect();
err.note(format!(
"register class `{}` supports these types: {}",
reg_class.name(),
supported_tys.join(", "),
));
if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
- err.help(format!(
- "consider using the `{}` register class instead",
- suggest.name()
- ));
+ err.help(format!("consider using the `{}` register class instead", suggest.name()));
}
err.emit();
return Some(asm_ty);
@@ -215,7 +211,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// register class is usable at all.
if let Some(feature) = feature {
if !target_features.contains(feature) {
- let msg = format!("`{}` target feature is not enabled", feature);
+ let msg = format!("`{feature}` target feature is not enabled");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(format!(
"this is required to use type `{}` with register class `{}`",
@@ -427,7 +423,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that sym actually points to a function. Later passes
// depend on this.
hir::InlineAsmOperand::SymFn { anon_const } => {
- let ty = self.tcx.type_of(anon_const.def_id).subst_identity();
+ let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
match ty.kind() {
ty::Never | ty::Error(_) => {}
ty::FnDef(..) => {}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index ce2da7cb1..4cf358732 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -38,7 +38,7 @@ can be broken down into several distinct phases:
While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
-stored in `fcx.node_types` and `fcx.node_substs`. These types
+stored in `fcx.node_types` and `fcx.node_args`. These types
may contain unresolved type variables. After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
@@ -65,6 +65,7 @@ a type parameter).
mod check;
mod compare_impl_item;
pub mod dropck;
+mod entry;
pub mod intrinsic;
pub mod intrinsicck;
mod region;
@@ -80,7 +81,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::parse::feature_err;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, Ident};
@@ -188,7 +189,7 @@ fn missing_items_err(
full_impl_span: Span,
) {
let missing_items =
- missing_items.iter().filter(|trait_item| trait_item.opt_rpitit_info.is_none());
+ missing_items.iter().filter(|trait_item| !trait_item.is_impl_trait_in_trait());
let missing_items_msg = missing_items
.clone()
@@ -211,9 +212,9 @@ fn missing_items_err(
let snippet = suggestion_signature(
tcx,
trait_item,
- tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+ tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
);
- let code = format!("{}{}\n{}", padding, snippet, padding);
+ let code = format!("{padding}{snippet}\n{padding}");
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
missing_trait_item_label
.push(errors::MissingTraitItemLabel { span, item: trait_item.name });
@@ -408,7 +409,7 @@ fn fn_sig_suggestion<'tcx>(
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
output = if let ty::Alias(_, alias_ty) = *output.kind() {
tcx.explicit_item_bounds(alias_ty.def_id)
- .subst_iter_copied(tcx, alias_ty.substs)
+ .iter_instantiated_copied(tcx, alias_ty.args)
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
.unwrap_or_else(|| {
span_bug!(
@@ -461,10 +462,10 @@ fn suggestion_signature<'tcx>(
assoc: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> String {
- let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+ let args = ty::GenericArgs::identity_for_item(tcx, assoc.def_id).rebase_onto(
tcx,
assoc.container_id(tcx),
- impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+ impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).args,
);
match assoc.kind {
@@ -472,21 +473,21 @@ fn suggestion_signature<'tcx>(
tcx,
tcx.liberate_late_bound_regions(
assoc.def_id,
- tcx.fn_sig(assoc.def_id).subst(tcx, substs),
+ tcx.fn_sig(assoc.def_id).instantiate(tcx, args),
),
assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
assoc,
),
ty::AssocKind::Type => {
let (generics, where_clauses) = bounds_from_generic_predicates(
tcx,
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
);
format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
}
ty::AssocKind::Const => {
- let ty = tcx.type_of(assoc.def_id).subst_identity();
+ let ty = tcx.type_of(assoc.def_id).instantiate_identity();
let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
format!("const {}: {} = {};", assoc.name, ty, val)
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d4748b7ef..f5beefc47 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -5,7 +5,7 @@ use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
@@ -18,7 +18,7 @@ use rustc_middle::ty::{
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor,
};
-use rustc_middle::ty::{GenericArgKind, InternalSubsts};
+use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -75,12 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.body_def_id,
ObligationCauseCode::WellFormed(loc),
);
- // for a type to be WF, we do not need to check if const trait predicates satisfy.
- let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
self.tcx(),
cause,
- param_env,
+ self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
@@ -196,7 +194,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match (tcx.impl_polarity(def_id), impl_.polarity) {
(ty::ImplPolarity::Positive, _) => {
- check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness);
+ check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
}
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
@@ -247,10 +245,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
- hir::ItemKind::TyAlias(hir_ty, ..) => {
- if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
- // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
+ hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
+ if tcx.features().lazy_type_alias
+ || tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
+ {
+ // Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
+ // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+ check_variances_for_type_defn(tcx, item, ast_generics);
}
}
_ => {}
@@ -286,11 +288,22 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, def_id, span, method_sig);
+
+ if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
+ for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
+ check_associated_item(
+ tcx,
+ assoc_ty_def_id.expect_local(),
+ tcx.def_span(assoc_ty_def_id),
+ None,
+ );
+ }
+ }
}
/// Require that the user writes where clauses on GATs for the implicit
/// outlives bounds involving trait parameters in trait functions and
-/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+/// lifetimes passed as GAT args. See `self-outlives-lint` test.
///
/// We use the following trait as an example throughout this function:
/// ```rust,ignore (this code fails due to this lint)
@@ -314,7 +327,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
for gat_item in associated_items {
let gat_def_id = gat_item.id.owner_id;
let gat_item = tcx.associated_item(gat_def_id);
- // If this item is not an assoc ty, or has no substs, then it's not a GAT
+ // If this item is not an assoc ty, or has no args, then it's not a GAT
if gat_item.kind != ty::AssocKind::Type {
continue;
}
@@ -345,7 +358,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(
item_def_id.to_def_id(),
- tcx.fn_sig(item_def_id).subst_identity(),
+ tcx.fn_sig(item_def_id).instantiate_identity(),
);
gather_gat_bounds(
tcx,
@@ -374,7 +387,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
param_env,
item_def_id,
tcx.explicit_item_bounds(item_def_id)
- .subst_identity_iter_copied()
+ .instantiate_identity_iter_copied()
.collect::<Vec<_>>(),
&FxIndexSet::default(),
gat_def_id.def_id,
@@ -472,8 +485,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let bound =
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
err.note(format!(
- "{} currently required to ensure that impls have maximum flexibility",
- bound
+ "{bound} currently required to ensure that impls have maximum flexibility"
));
err.note(
"we are soliciting feedback, see issue #87479 \
@@ -505,7 +517,7 @@ fn augment_param_env<'tcx>(
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
- ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness())
+ ty::ParamEnv::new(bounds, param_env.reveal())
}
/// We use the following trait as an example throughout this function.
@@ -544,8 +556,8 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
for (region_a, region_a_idx) in &regions {
// Ignore `'static` lifetimes for the purpose of this lint: it's
// because we know it outlives everything and so doesn't give meaningful
- // clues
- if let ty::ReStatic = **region_a {
+ // clues. Also ignore `ReError`, to avoid knock-down errors.
+ if let ty::ReStatic | ty::ReError(_) = **region_a {
continue;
}
// For each region argument (e.g., `'a` in our example), check for a
@@ -588,8 +600,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// on the GAT itself.
for (region_b, region_b_idx) in &regions {
// Again, skip `'static` because it outlives everything. Also, we trivially
- // know that a region outlives itself.
- if ty::ReStatic == **region_b || region_a == region_b {
+ // know that a region outlives itself. Also ignore `ReError`, to avoid
+ // knock-down errors.
+ if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
continue;
}
if region_known_to_outlive(
@@ -737,7 +750,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
- for (idx, subst) in p.substs.iter().enumerate() {
+ for (idx, subst) in p.args.iter().enumerate() {
match subst.unpack() {
GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
self.regions.insert((lt, idx));
@@ -836,7 +849,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
// Const parameters are well formed if their type is structural match.
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
- let ty = tcx.type_of(param.def_id).subst_identity();
+ let ty = tcx.type_of(param.def_id).instantiate_identity();
if tcx.features().adt_const_params {
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
@@ -910,17 +923,17 @@ fn check_associated_item(
let self_ty = match item.container {
ty::TraitContainer => tcx.types.self_param,
- ty::ImplContainer => tcx.type_of(item.container_id(tcx)).subst_identity(),
+ ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
};
match item.kind {
ty::AssocKind::Const => {
- let ty = tcx.type_of(item.def_id).subst_identity();
+ let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
ty::AssocKind::Fn => {
- let sig = tcx.fn_sig(item.def_id).subst_identity();
+ let sig = tcx.fn_sig(item.def_id).instantiate_identity();
let hir_sig = sig_if_method.expect("bad signature for method");
check_fn_or_method(
wfcx,
@@ -936,7 +949,7 @@ fn check_associated_item(
check_associated_type_bounds(wfcx, item, span)
}
if item.defaultness(tcx).has_value() {
- let ty = tcx.type_of(item.def_id).subst_identity();
+ let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
@@ -969,7 +982,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir().get_by_def_id(field_id).expect_field();
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
+ let ty = wfcx.normalize(
+ hir_ty.span,
+ None,
+ tcx.type_of(field.did).instantiate_identity(),
+ );
wfcx.register_wf_obligation(
hir_ty.span,
Some(WellFormedLoc::Ty(field_id)),
@@ -981,11 +998,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.tail().did).subst_identity();
+ let ty = tcx.type_of(variant.tail().did).instantiate_identity();
let ty = tcx.erase_regions(ty);
if ty.has_infer() {
tcx.sess
- .delay_span_bug(item.span, format!("inference variables in {:?}", ty));
+ .delay_span_bug(item.span, format!("inference variables in {ty:?}"));
// Just treat unresolved type expression as if it needs drop.
true
} else {
@@ -1003,7 +1020,11 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir().get_by_def_id(field_id).expect_field();
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
+ let ty = wfcx.normalize(
+ hir_ty.span,
+ None,
+ tcx.type_of(field.did).instantiate_identity(),
+ );
wfcx.register_bound(
traits::ObligationCause::new(
hir_ty.span,
@@ -1083,16 +1104,17 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
debug!("check_associated_type_bounds: bounds={:?}", bounds);
- let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
- let normalized_bound = wfcx.normalize(span, None, bound);
- traits::wf::predicate_obligations(
- wfcx.infcx,
- wfcx.param_env,
- wfcx.body_def_id,
- normalized_bound.as_predicate(),
- bound_span,
- )
- });
+ let wf_obligations =
+ bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
+ let normalized_bound = wfcx.normalize(span, None, bound);
+ traits::wf::predicate_obligations(
+ wfcx.infcx,
+ wfcx.param_env,
+ wfcx.body_def_id,
+ normalized_bound.as_predicate(),
+ bound_span,
+ )
+ });
wfcx.register_obligations(wf_obligations);
}
@@ -1105,7 +1127,7 @@ fn check_item_fn(
decl: &hir::FnDecl<'_>,
) {
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
- let sig = tcx.fn_sig(def_id).subst_identity();
+ let sig = tcx.fn_sig(def_id).instantiate_identity();
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
})
}
@@ -1125,7 +1147,7 @@ fn check_item_type(
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
- let ty = tcx.type_of(item_id).subst_identity();
+ let ty = tcx.type_of(item_id).instantiate_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let forbid_unsized = match unsized_handling {
@@ -1170,7 +1192,6 @@ fn check_impl<'tcx>(
item: &'tcx hir::Item<'tcx>,
ast_self_ty: &hir::Ty<'_>,
ast_trait_ref: &Option<hir::TraitRef<'_>>,
- constness: hir::Constness,
) {
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match ast_trait_ref {
@@ -1178,20 +1199,14 @@ fn check_impl<'tcx>(
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
- let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
let trait_ref = wfcx.normalize(
ast_trait_ref.path.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
trait_ref,
);
- let trait_pred = ty::TraitPredicate {
- trait_ref,
- constness: match constness {
- hir::Constness::Const => ty::BoundConstness::ConstIfConst,
- hir::Constness::NotConst => ty::BoundConstness::NotConst,
- },
- polarity: ty::ImplPolarity::Positive,
- };
+ let trait_pred =
+ ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive };
let mut obligations = traits::wf::trait_obligations(
wfcx.infcx,
wfcx.param_env,
@@ -1211,7 +1226,7 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
- let self_ty = tcx.type_of(item.owner_id).subst_identity();
+ let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
let self_ty = wfcx.normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1256,7 +1271,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
match param.kind {
GenericParamDefKind::Type { .. } => {
if is_our_default(param) {
- let ty = tcx.type_of(param.def_id).subst_identity();
+ let ty = tcx.type_of(param.def_id).instantiate_identity();
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
@@ -1272,10 +1287,10 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Const { .. } => {
if is_our_default(param) {
// FIXME(const_generics_defaults): This
- // is incorrect when dealing with unused substs, for example
+ // is incorrect when dealing with unused args, for example
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
// we should eagerly error.
- let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+ let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
if !default_ct.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
@@ -1298,7 +1313,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
//
// First we build the defaulted substitution.
- let substs = InternalSubsts::for_item(tcx, def_id.to_def_id(), |param, _| {
+ let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
// All regions are identity.
@@ -1308,7 +1323,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Type { .. } => {
// If the param has a default, ...
if is_our_default(param) {
- let default_ty = tcx.type_of(param.def_id).subst_identity();
+ let default_ty = tcx.type_of(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ty.has_param() {
// ... then substitute it with the default.
@@ -1321,7 +1336,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Const { .. } => {
// If the param has a default, ...
if is_our_default(param) {
- let default_ct = tcx.const_param_default(param.def_id).subst_identity();
+ let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ct.has_param() {
// ... then substitute it with the default.
@@ -1366,7 +1381,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
- let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
+ let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
@@ -1407,7 +1422,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations(
infcx,
- wfcx.param_env.without_const(),
+ wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,
@@ -1460,13 +1475,6 @@ fn check_fn_or_method<'tcx>(
check_where_clauses(wfcx, span, def_id);
- check_return_position_impl_trait_in_trait_bounds(
- wfcx,
- def_id,
- sig.output(),
- hir_decl.output.span(),
- );
-
if sig.abi == Abi::RustCall {
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
@@ -1501,87 +1509,6 @@ fn check_fn_or_method<'tcx>(
}
}
-/// Basically `check_associated_type_bounds`, but separated for now and should be
-/// deduplicated when RPITITs get lowered into real associated items.
-#[tracing::instrument(level = "trace", skip(wfcx))]
-fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
- wfcx: &WfCheckingCtxt<'_, 'tcx>,
- fn_def_id: LocalDefId,
- fn_output: Ty<'tcx>,
- span: Span,
-) {
- let tcx = wfcx.tcx();
- let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
- return;
- };
- if assoc_item.container != ty::AssocItemContainer::TraitContainer {
- return;
- }
- fn_output.visit_with(&mut ImplTraitInTraitFinder {
- wfcx,
- fn_def_id,
- depth: ty::INNERMOST,
- seen: FxHashSet::default(),
- });
-}
-
-// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
-// strategy, we can't just call `check_associated_item` on the new RPITITs,
-// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
-// That's because we need to check that the bounds of the RPITIT hold using
-// the special substs that we create during opaque type lowering, otherwise we're
-// getting a bunch of early bound and free regions mixed up... Haven't looked too
-// deep into this, though.
-struct ImplTraitInTraitFinder<'a, 'tcx> {
- wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
- fn_def_id: LocalDefId,
- depth: ty::DebruijnIndex,
- seen: FxHashSet<DefId>,
-}
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
- type BreakTy = !;
-
- fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
- let tcx = self.wfcx.tcx();
- if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
- && self.seen.insert(unshifted_opaque_ty.def_id)
- && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
- && let origin = tcx.opaque_type_origin(opaque_def_id)
- && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
- && source == self.fn_def_id
- {
- let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
- match re.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
- r => bug!("unexpected region: {r:?}"),
- }
- });
- for (bound, bound_span) in tcx
- .explicit_item_bounds(opaque_ty.def_id)
- .subst_iter_copied(tcx, opaque_ty.substs)
- {
- let bound = self.wfcx.normalize(bound_span, None, bound);
- self.wfcx.register_obligations(traits::wf::predicate_obligations(
- self.wfcx.infcx,
- self.wfcx.param_env,
- self.wfcx.body_def_id,
- bound.as_predicate(),
- bound_span,
- ));
- // Set the debruijn index back to innermost here, since we already eagerly
- // shifted the substs that we use to generate these bounds. This is unfortunately
- // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
- // but that function doesn't actually need to normalize the bound it's visiting
- // (whereas we have to do so here)...
- let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
- bound.visit_with(self);
- self.depth = old_depth;
- }
- }
- ty.super_visit_with(self)
- }
-}
-
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
of the previous types except `Self`)";
@@ -1601,7 +1528,7 @@ fn check_method_receiver<'tcx>(
let span = fn_sig.decl.inputs[0].span;
- let sig = tcx.fn_sig(method.def_id).subst_identity();
+ let sig = tcx.fn_sig(method.def_id).instantiate_identity();
let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
let sig = wfcx.normalize(span, None, sig);
@@ -1773,11 +1700,28 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let identity_substs = ty::InternalSubsts::identity_for_item(tcx, item.owner_id);
- for field in tcx.adt_def(item.owner_id).all_fields() {
- if field.ty(tcx, identity_substs).references_error() {
- return;
+ let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
+
+ match item.kind {
+ ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
+ for field in tcx.adt_def(item.owner_id).all_fields() {
+ if field.ty(tcx, identity_args).references_error() {
+ return;
+ }
+ }
+ }
+ ItemKind::TyAlias(..) => {
+ let ty = tcx.type_of(item.owner_id).instantiate_identity();
+
+ if tcx.features().lazy_type_alias || ty.has_opaque_types() {
+ if ty.references_error() {
+ return;
+ }
+ } else {
+ bug!();
+ }
}
+ _ => bug!(),
}
let ty_predicates = tcx.predicates_of(item.owner_id);
@@ -1854,8 +1798,7 @@ fn report_bivariance(
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
err.help(format!(
- "if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
- param_name
+ "if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead"
));
}
err.emit()
@@ -1911,7 +1854,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
}
}
-fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
+fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) {
let items = tcx.hir_module_items(module);
items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 268b9ac53..9ad73eeff 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -1,12 +1,21 @@
-use rustc_data_structures::unord::UnordSet;
+use rustc_data_structures::unord::{ExtendUnord, UnordSet};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
+use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
-pub fn check_crate(tcx: TyCtxt<'_>) {
- let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { check_unused_traits, ..*providers };
+}
+
+fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
+ let mut used_trait_imports = UnordSet::<LocalDefId>::default();
+ // FIXME: Use `tcx.hir().par_body_owners()` when we implement creating `DefId`s
+ // for anon constants during their parents' typeck.
+ // Doing so at current will produce queries cycle errors because it may typeck
+ // on anon constants directly.
for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
@@ -27,7 +36,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
}
let (path, _) = item.expect_use();
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
- format!("unused import: `{}`", snippet)
+ format!("unused import: `{snippet}`")
} else {
"unused import".to_owned()
};
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 79cc43edf..c930537d4 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -57,7 +57,7 @@ impl<'tcx> Checker<'tcx> {
fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
// Destructors only work on local ADT types.
- match tcx.type_of(impl_did).subst_identity().kind() {
+ match tcx.type_of(impl_did).instantiate_identity().kind() {
ty::Adt(def, _) if def.did().is_local() => return,
ty::Error(_) => return,
_ => {}
@@ -71,7 +71,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
- let self_type = tcx.type_of(impl_did).subst_identity();
+ let self_type = tcx.type_of(impl_did).instantiate_identity();
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
let param_env = tcx.param_env(impl_did);
@@ -100,7 +100,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
}
fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
- let self_type = tcx.type_of(impl_did).subst_identity();
+ let self_type = tcx.type_of(impl_did).instantiate_identity();
assert!(!self_type.has_escaping_bound_vars());
let param_env = tcx.param_env(impl_did);
@@ -139,13 +139,13 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
- let source = tcx.type_of(impl_did).subst_identity();
+ let source = tcx.type_of(impl_did).instantiate_identity();
assert!(!source.has_escaping_bound_vars());
let target = {
- let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
- trait_ref.substs.type_at(1)
+ trait_ref.args.type_at(1)
};
debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
@@ -163,9 +163,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
&& mutbl_a == *mutbl_b => {}
(&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
- (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
- if def_a.is_struct() && def_b.is_struct() =>
- {
+ (&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => {
if def_a != def_b {
let source_path = tcx.def_path_str(def_a.did());
let target_path = tcx.def_path_str(def_b.did());
@@ -173,8 +171,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
create_err(&format!(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures with the same \
- definition; expected `{}`, found `{}`",
- source_path, target_path,
+ definition; expected `{source_path}`, found `{target_path}`",
))
.emit();
@@ -194,8 +191,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
let coerced_fields = fields
.iter()
.filter(|field| {
- let ty_a = field.ty(tcx, substs_a);
- let ty_b = field.ty(tcx, substs_b);
+ let ty_a = field.ty(tcx, args_a);
+ let ty_b = field.ty(tcx, args_b);
if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
if layout.is_zst() && layout.align.abi.bytes() == 1 {
@@ -250,8 +247,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
format!(
"`{}` (`{}` to `{}`)",
field.name,
- field.ty(tcx, substs_a),
- field.ty(tcx, substs_b),
+ field.ty(tcx, args_a),
+ field.ty(tcx, args_b),
)
})
.collect::<Vec<_>>()
@@ -268,7 +265,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
ty::TraitRef::new(
tcx,
dispatch_from_dyn_trait,
- [field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
+ [field.ty(tcx, args_a), field.ty(tcx, args_b)],
),
));
}
@@ -300,10 +297,10 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
- let source = tcx.type_of(impl_did).subst_identity();
- let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
+ let source = tcx.type_of(impl_did).instantiate_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
assert_eq!(trait_ref.def_id, coerce_unsized_trait);
- let target = trait_ref.substs.type_at(1);
+ let target = trait_ref.args.type_at(1);
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
let param_env = tcx.param_env(impl_did);
@@ -348,7 +345,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
}
- (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
+ (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
if def_a.is_struct() && def_b.is_struct() =>
{
if def_a != def_b {
@@ -411,9 +408,9 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
let diff_fields = fields
.iter_enumerated()
.filter_map(|(i, f)| {
- let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
+ let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
- if tcx.type_of(f.did).subst_identity().is_phantom_data() {
+ if tcx.type_of(f.did).instantiate_identity().is_phantom_data() {
// Ignore PhantomData fields
return None;
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 335590206..a94c75f91 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -148,8 +148,7 @@ impl<'tcx> InherentCollect<'tcx> {
if let ty::Ref(_, subty, _) = ty.kind() {
err.note(format!(
"you could also try moving the reference to \
- uses of `{}` (such as `self`) within the implementation",
- subty
+ uses of `{subty}` (such as `self`) within the implementation"
));
}
err.emit();
@@ -171,7 +170,7 @@ impl<'tcx> InherentCollect<'tcx> {
let id = id.owner_id.def_id;
let item_span = self.tcx.def_span(id);
- let self_ty = self.tcx.type_of(id).subst_identity();
+ let self_ty = self.tcx.type_of(id).instantiate_identity();
match *self_ty.kind() {
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 3bd293126..7205b7a21 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -77,8 +77,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
"duplicate definitions with name `{}`",
ident,
);
- err.span_label(span, format!("duplicate definitions for `{}`", ident));
- err.span_label(*former, format!("other definition for `{}`", ident));
+ err.span_label(span, format!("duplicate definitions for `{ident}`"));
+ err.span_label(*former, format!("other definition for `{ident}`"));
err.emit();
}
@@ -114,11 +114,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
);
err.span_label(
self.tcx.def_span(item1.def_id),
- format!("duplicate definitions for `{}`", name),
+ format!("duplicate definitions for `{name}`"),
);
err.span_label(
self.tcx.def_span(item2.def_id),
- format!("other definition for `{}`", name),
+ format!("other definition for `{name}`"),
);
for cause in &overlap.intercrate_ambiguity_causes {
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 5097f4360..fc8fab0ea 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -122,7 +122,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
let impls = tcx.hir().trait_impls(def_id);
for &impl_def_id in impls {
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
check_impl(tcx, impl_def_id, trait_ref);
check_object_overlap(tcx, impl_def_id, trait_ref);
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 025bab140..bbdb108c5 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{
self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor,
@@ -22,7 +22,7 @@ pub(crate) fn orphan_check_impl(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
trait_ref.error_reported()?;
let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id);
@@ -352,7 +352,7 @@ fn emit_orphan_check_error<'tcx>(
let this = |name: &str| {
if !trait_ref.def_id.is_local() && !is_target_ty {
- msg("this", &format!(" because this is a foreign trait"))
+ msg("this", " because this is a foreign trait")
} else {
msg("this", &format!(" because {name} are always foreign"))
}
@@ -412,9 +412,8 @@ fn emit_orphan_check_error<'tcx>(
.span_label(
sp,
format!(
- "type parameter `{}` must be covered by another type \
- when it appears before the first local type (`{}`)",
- param_ty, local_type
+ "type parameter `{param_ty}` must be covered by another type \
+ when it appears before the first local type (`{local_type}`)"
),
)
.note(
@@ -441,9 +440,8 @@ fn emit_orphan_check_error<'tcx>(
.span_label(
sp,
format!(
- "type parameter `{}` must be used as the type parameter for some \
+ "type parameter `{param_ty}` must be used as the type parameter for some \
local type",
- param_ty,
),
)
.note(
@@ -488,10 +486,10 @@ fn lint_auto_trait_impl<'tcx>(
trait_ref: ty::TraitRef<'tcx>,
impl_def_id: LocalDefId,
) {
- assert_eq!(trait_ref.substs.len(), 1);
+ assert_eq!(trait_ref.args.len(), 1);
let self_ty = trait_ref.self_ty();
- let (self_type_did, substs) = match self_ty.kind() {
- ty::Adt(def, substs) => (def.did(), substs),
+ let (self_type_did, args) = match self_ty.kind() {
+ ty::Adt(def, args) => (def.did(), args),
_ => {
// FIXME: should also lint for stuff like `&i32` but
// considering that auto traits are unstable, that
@@ -502,9 +500,9 @@ fn lint_auto_trait_impl<'tcx>(
};
// Impls which completely cover a given root type are fine as they
- // disable auto impls entirely. So only lint if the substs
- // are not a permutation of the identity substs.
- let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
+ // disable auto impls entirely. So only lint if the args
+ // are not a permutation of the identity args.
+ let Err(arg) = tcx.uses_unique_generic_params(args, CheckRegions::No) else {
// ok
return;
};
@@ -541,17 +539,16 @@ fn lint_auto_trait_impl<'tcx>(
let self_descr = tcx.def_descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
- lint.note(format!("`{}` is mentioned multiple times", arg));
+ lint.note(format!("`{arg}` is mentioned multiple times"));
}
ty::util::NotUniqueParam::NotParam(arg) => {
- lint.note(format!("`{}` is not a generic parameter", arg));
+ lint.note(format!("`{arg}` is not a generic parameter"));
}
}
lint.span_note(
item_span,
format!(
- "try using the same sequence of generic parameters as the {} definition",
- self_descr,
+ "try using the same sequence of generic parameters as the {self_descr} definition",
),
)
},
@@ -568,10 +565,10 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for DisableAutoTraitVisitor<'tcx> {
type BreakTy = ();
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let tcx = self.tcx;
- if t != self.self_ty_root {
- for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) {
+ if ty != self.self_ty_root {
+ for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, ty) {
match tcx.impl_polarity(impl_def_id) {
ImplPolarity::Negative => return ControlFlow::Break(()),
ImplPolarity::Reservation => {}
@@ -584,30 +581,28 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
}
}
- match t.kind() {
- ty::Adt(def, substs) if def.is_phantom_data() => substs.visit_with(self),
- ty::Adt(def, substs) => {
+ match ty.kind() {
+ ty::Adt(def, args) if def.is_phantom_data() => args.visit_with(self),
+ ty::Adt(def, args) => {
// @lcnr: This is the only place where cycles can happen. We avoid this
// by only visiting each `DefId` once.
//
// This will be is incorrect in subtle cases, but I don't care :)
if self.seen.insert(def.did()) {
- for ty in def.all_fields().map(|field| field.ty(tcx, substs)) {
+ for ty in def.all_fields().map(|field| field.ty(tcx, args)) {
ty.visit_with(self)?;
}
}
ControlFlow::Continue(())
}
- _ => t.super_visit_with(self),
+ _ => ty.super_visit_with(self),
}
}
}
let self_ty_root = match self_ty.kind() {
- ty::Adt(def, _) => {
- Ty::new_adt(tcx, *def, InternalSubsts::identity_for_item(tcx, def.did()))
- }
+ ty::Adt(def, _) => Ty::new_adt(tcx, *def, GenericArgs::identity_for_item(tcx, def.did())),
_ => unimplemented!("unexpected self ty {:?}", self_ty),
};
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index c6b161713..6b18b0ebe 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -12,7 +12,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let impl_ = item.expect_impl();
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
- let trait_ref = trait_ref.subst_identity();
+ let trait_ref = trait_ref.instantiate_identity();
let trait_def = tcx.trait_def(trait_ref.def_id);
let unsafe_attr =
impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f47df4f21..7b9f61d7a 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -22,7 +22,7 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -48,7 +48,7 @@ mod type_of;
///////////////////////////////////////////////////////////////////////////
// Main entry point
-fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
+fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
}
@@ -195,9 +195,9 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
sugg.push((arg.span, (*type_name).to_string()));
} else if let Some(span) = generics.span_for_param_suggestion() {
// Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
- sugg.push((span, format!(", {}", type_name)));
+ sugg.push((span, format!(", {type_name}")));
} else {
- sugg.push((generics.span, format!("<{}>", type_name)));
+ sugg.push((generics.span, format!("<{type_name}>")));
}
}
@@ -329,7 +329,7 @@ fn bad_placeholder<'tcx>(
mut spans: Vec<Span>,
kind: &'static str,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
+ let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };
spans.sort();
tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
@@ -401,13 +401,13 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
- let item_substs = self.astconv().create_substs_for_associated_item(
+ let item_args = self.astconv().create_args_for_associated_item(
span,
item_def_id,
item_segment,
- trait_ref.substs,
+ trait_ref.args,
);
- Ty::new_projection(self.tcx(), item_def_id, item_substs)
+ Ty::new_projection(self.tcx(), item_def_id, item_args)
} else {
// There are no late-bound regions; we can just ignore the binder.
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -425,10 +425,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
| hir::ItemKind::Union(_, generics) => {
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
let (lt_sp, sugg) = match generics.params {
- [] => (generics.span, format!("<{}>", lt_name)),
- [bound, ..] => {
- (bound.span.shrink_to_lo(), format!("{}, ", lt_name))
- }
+ [] => (generics.span, format!("<{lt_name}>")),
+ [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
};
mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
fspan: lt_sp,
@@ -1027,7 +1025,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
} else {
tcx.sess.span_err(
meta.span(),
- format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
+ format!("unknown meta item passed to `rustc_deny_explicit_impl` {meta:?}"),
);
}
}
@@ -1145,8 +1143,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
}
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
- let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity();
- let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).subst_identity());
+ let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity();
+ let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
ty::Binder::dummy(tcx.mk_fn_sig(
inputs,
ty,
@@ -1161,15 +1159,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
// signatures and cannot be accessed through `fn_sig`. For
// example, a closure signature excludes the `self`
// argument. In any case they are embedded within the
- // closure type as part of the `ClosureSubsts`.
+ // closure type as part of the `ClosureArgs`.
//
// To get the signature of a closure, you should use the
- // `sig` method on the `ClosureSubsts`:
+ // `sig` method on the `ClosureArgs`:
//
- // substs.as_closure().sig(def_id, tcx)
- bug!(
- "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
- );
+ // args.as_closure().sig(def_id, tcx)
+ bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
}
x => {
@@ -1266,7 +1262,7 @@ fn suggest_impl_trait<'tcx>(
) -> Option<String> {
let format_as_assoc: fn(_, _, _, _, _) -> _ =
|tcx: TyCtxt<'tcx>,
- _: ty::SubstsRef<'tcx>,
+ _: ty::GenericArgsRef<'tcx>,
trait_def_id: DefId,
assoc_item_def_id: DefId,
item_ty: Ty<'tcx>| {
@@ -1276,13 +1272,15 @@ fn suggest_impl_trait<'tcx>(
};
let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
|tcx: TyCtxt<'tcx>,
- substs: ty::SubstsRef<'tcx>,
+ args: ty::GenericArgsRef<'tcx>,
trait_def_id: DefId,
_: DefId,
item_ty: Ty<'tcx>| {
let trait_name = tcx.item_name(trait_def_id);
- let args_tuple = substs.type_at(1);
- let ty::Tuple(types) = *args_tuple.kind() else { return None; };
+ let args_tuple = args.type_at(1);
+ let ty::Tuple(types) = *args_tuple.kind() else {
+ return None;
+ };
let types = types.make_suggestable(tcx, false)?;
let maybe_ret =
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
@@ -1315,31 +1313,34 @@ fn suggest_impl_trait<'tcx>(
format_as_parenthesized,
),
] {
- let Some(trait_def_id) = trait_def_id else { continue; };
- let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
+ let Some(trait_def_id) = trait_def_id else {
+ continue;
+ };
+ let Some(assoc_item_def_id) = assoc_item_def_id else {
+ continue;
+ };
if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
continue;
}
let param_env = tcx.param_env(def_id);
let infcx = tcx.infer_ctxt().build();
- let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+ let args = ty::GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
});
- if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
- {
+ if !infcx.type_implements_trait(trait_def_id, args, param_env).must_apply_modulo_regions() {
continue;
}
let ocx = ObligationCtxt::new(&infcx);
let item_ty = ocx.normalize(
&ObligationCause::misc(span, def_id),
param_env,
- Ty::new_projection(tcx, assoc_item_def_id, substs),
+ Ty::new_projection(tcx, assoc_item_def_id, args),
);
// FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty()
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
&& let Some(item_ty) = item_ty.make_suggestable(tcx, false)
- && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
+ && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(args), trait_def_id, assoc_item_def_id, item_ty)
{
return Some(sugg);
}
@@ -1357,39 +1358,61 @@ fn impl_trait_ref(
.of_trait
.as_ref()
.map(|ast_trait_ref| {
- let selfty = tcx.type_of(def_id).subst_identity();
- icx.astconv().instantiate_mono_trait_ref(
- ast_trait_ref,
- selfty,
- check_impl_constness(tcx, impl_.constness, ast_trait_ref),
- )
+ let selfty = tcx.type_of(def_id).instantiate_identity();
+
+ if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
+ tcx,
+ tcx.is_const_trait_impl_raw(def_id.to_def_id()),
+ &ast_trait_ref,
+ ) {
+ // we have a const impl, but for a trait without `#[const_trait]`, so
+ // without the host param. If we continue with the HIR trait ref, we get
+ // ICEs for generic arg count mismatch. We do a little HIR editing to
+ // make astconv happy.
+ let mut path_segments = ast_trait_ref.path.segments.to_vec();
+ let last_segment = path_segments.len() - 1;
+ let mut args = path_segments[last_segment].args().clone();
+ let last_arg = args.args.len() - 1;
+ assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host)));
+ args.args = &args.args[..args.args.len() - 1];
+ path_segments[last_segment].args = Some(&args);
+ let path = hir::Path {
+ span: ast_trait_ref.path.span,
+ res: ast_trait_ref.path.res,
+ segments: &path_segments,
+ };
+ let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id };
+ icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty)
+ } else {
+ icx.astconv().instantiate_mono_trait_ref(&ast_trait_ref, selfty)
+ }
})
.map(ty::EarlyBinder::bind)
}
fn check_impl_constness(
tcx: TyCtxt<'_>,
- constness: hir::Constness,
+ is_const: bool,
ast_trait_ref: &hir::TraitRef<'_>,
-) -> ty::BoundConstness {
- match constness {
- hir::Constness::Const => {
- if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
- let trait_name = tcx.item_name(trait_def_id).to_string();
- tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
- trait_ref_span: ast_trait_ref.path.span,
- trait_name,
- local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
- marking: (),
- adding: (),
- });
- ty::BoundConstness::NotConst
- } else {
- ty::BoundConstness::ConstIfConst
- }
- },
- hir::Constness::NotConst => ty::BoundConstness::NotConst,
+) -> Option<ErrorGuaranteed> {
+ if !is_const {
+ return None;
+ }
+
+ let trait_def_id = ast_trait_ref.trait_def_id()?;
+ if tcx.has_attr(trait_def_id, sym::const_trait) {
+ return None;
}
+
+ let trait_name = tcx.item_name(trait_def_id).to_string();
+ Some(tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
+ trait_ref_span: ast_trait_ref.path.span,
+ trait_name,
+ local_trait_span:
+ trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
+ marking: (),
+ adding: (),
+ }))
}
fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
@@ -1502,7 +1525,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
.sess
.source_map()
.span_to_snippet(ast_ty.span)
- .map_or_else(|_| String::new(), |s| format!(" `{}`", s));
+ .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
}
};
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index ccc9f8084..484200827 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -68,17 +68,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// ^ parent_def_id
//
// then we only want to return generics for params to the left of `N`. If we don't do that we
- // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
+ // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`.
//
- // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
- // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
- // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
+ // This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as
+ // we substitute the defaults with the partially built args when we build the args. Subst'ing
+ // the `N#0` on the unevaluated const indexes into the empty args we're in the process of building.
//
// We fix this by having this function return the parent's generics ourselves and truncating the
// generics to only include non-forward declared params (with the exception of the `Self` ty)
//
- // For the above code example that means we want `substs: []`
- // For the following struct def we want `substs: [N#0]` when generics_of is called on
+ // For the above code example that means we want `args: []`
+ // For the following struct def we want `args: [N#0]` when generics_of is called on
// the def id of the `{ N + 1 }` anon const
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
//
@@ -93,7 +93,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
return ty::Generics {
// we set the parent of these generics to be our parent's parent so that we
- // dont end up with substs: [N, M, N] for the const default on a struct like this:
+ // dont end up with args: [N, M, N] for the const default on a struct like this:
// struct Foo<const N: usize, const M: usize = { ... }>;
parent: generics.parent,
parent_count: generics.parent_count,
@@ -209,6 +209,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
| ItemKind::Struct(..)
| ItemKind::OpaqueTy(..)
| ItemKind::Union(..) => (None, Defaults::Allowed),
+ ItemKind::Const(..) => (None, Defaults::Deny),
_ => (None, Defaults::FutureCompatDisallowed),
}
}
@@ -319,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
}
- host_effect_index = Some(parent_count + index as usize);
+ host_effect_index = Some(index as usize);
}
Some(ty::GenericParamDef {
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 57f74172e..4b7743fae 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -2,15 +2,15 @@ use super::ItemCtxt;
use crate::astconv::{AstConv, PredicateFilter};
use rustc_hir as hir;
use rustc_infer::traits::util;
-use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::GenericArgs;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
/// For associated types we include both bounds written on the type
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
///
-/// Note that this filtering is done with the items identity substs to
+/// Note that this filtering is done with the items identity args to
/// simplify checking that these bounds are met in impls. This means that
/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
/// `hr-associated-type-bound-1.rs`.
@@ -23,7 +23,7 @@ fn associated_type_bounds<'tcx>(
let item_ty = Ty::new_projection(
tcx,
assoc_item_def_id.to_def_id(),
- InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
+ GenericArgs::identity_for_item(tcx, assoc_item_def_id),
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
@@ -95,7 +95,7 @@ pub(super) fn explicit_item_bounds(
Ty::new_projection(
tcx,
def_id.to_def_id(),
- ty::InternalSubsts::identity_for_item(tcx, def_id),
+ ty::GenericArgs::identity_for_item(tcx, def_id),
),
item.span,
));
@@ -113,18 +113,35 @@ pub(super) fn explicit_item_bounds(
..
}) => associated_type_bounds(tcx, def_id, bounds, *span),
hir::Node::Item(hir::Item {
- kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
+ kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
span,
..
}) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
- Ty::new_projection(tcx, def_id.to_def_id(), substs)
- } else {
- Ty::new_opaque(tcx, def_id.to_def_id(), substs)
- };
+ let args = GenericArgs::identity_for_item(tcx, def_id);
+ let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
+ // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
+ // for the item bounds of the *opaques* in a trait's default method signature, we
+ // need to map these projections back to opaques.
+ hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: true, origin, .. }),
+ span,
+ ..
+ }) => {
+ let (hir::OpaqueTyOrigin::FnReturn(fn_def_id)
+ | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = *origin
+ else {
+ bug!()
+ };
+ let args = GenericArgs::identity_for_item(tcx, def_id);
+ let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
+ tcx.arena.alloc_slice(
+ &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
+ .to_vec()
+ .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
+ )
+ }
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
_ => bug!("item_bounds called on {:?}", def_id),
};
@@ -139,3 +156,26 @@ pub(super) fn item_bounds(
tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
})
}
+
+struct AssocTyToOpaque<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ fn_def_id: DefId,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTyToOpaque<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ if let ty::Alias(ty::Projection, projection_ty) = ty.kind()
+ && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. })
+ = self.tcx.opt_rpitit_info(projection_ty.def_id)
+ && fn_def_id == self.fn_def_id
+ {
+ self.tcx.type_of(projection_ty.def_id).instantiate(self.tcx, projection_ty.args)
+ } else {
+ ty
+ }
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 129366641..495e66366 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -2,17 +2,16 @@ use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
-use hir::{HirId, Lifetime, Node};
+use hir::{HirId, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
-use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, DUMMY_SP};
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -38,17 +37,10 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
// from the trait itself that *shouldn't* be shown as the source of
// an obligation and instead be skipped. Otherwise we'd use
// `tcx.def_span(def_id);`
-
- let constness = if tcx.has_attr(def_id, sym::const_trait) {
- ty::BoundConstness::ConstIfConst
- } else {
- ty::BoundConstness::NotConst
- };
-
let span = rustc_span::DUMMY_SP;
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
- ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
+ ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
span,
))));
}
@@ -63,33 +55,25 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
use rustc_hir::*;
match tcx.opt_rpitit_info(def_id.to_def_id()) {
- Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
- let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
- let opaque_ty_node = tcx.hir().get(opaque_ty_id);
- let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
- bug!("unexpected {opaque_ty_node:?}")
- };
-
+ Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
let mut predicates = Vec::new();
// RPITITs should inherit the predicates of their parent. This is
// both to ensure that the RPITITs are only instantiated when the
// parent predicates would hold, and also so that the param-env
// inherits these predicates as assumptions.
- let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
- predicates.extend(
- tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
- );
+ let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ predicates
+ .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
// We also install bidirectional outlives predicates for the RPITIT
// to keep the duplicates lifetimes from opaque lowering in sync.
+ // We only need to compute bidirectional outlives for the duplicated
+ // opaque lifetimes, which explains the slicing below.
compute_bidirectional_outlives_predicates(
tcx,
- def_id,
- lifetime_mapping.iter().map(|(lifetime, def_id)| {
- (*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
- }),
- tcx.generics_of(def_id.to_def_id()),
+ &tcx.generics_of(def_id.to_def_id()).params
+ [tcx.generics_of(fn_def_id).params.len()..],
&mut predicates,
);
@@ -104,15 +88,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let trait_assoc_predicates =
tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
- let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let impl_def_id = tcx.parent(fn_def_id);
- let impl_trait_ref_substs =
- tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
+ let impl_trait_ref_args =
+ tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
- let impl_assoc_substs =
- impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+ let impl_assoc_args =
+ impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
- let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+ let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
return ty::GenericPredicates {
parent: Some(impl_def_id),
@@ -146,13 +130,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
Node::Item(item) => match item.kind {
ItemKind::Impl(impl_) => {
if impl_.defaultness.is_default() {
- is_default_impl_trait =
- tcx.impl_trait_ref(def_id).map(|t| ty::Binder::dummy(t.subst_identity()));
+ is_default_impl_trait = tcx
+ .impl_trait_ref(def_id)
+ .map(|t| ty::Binder::dummy(t.instantiate_identity()));
}
impl_.generics
}
ItemKind::Fn(.., generics, _)
| ItemKind::TyAlias(_, generics)
+ | ItemKind::Const(_, generics, _)
| ItemKind::Enum(_, generics)
| ItemKind::Struct(_, generics)
| ItemKind::Union(_, generics) => generics,
@@ -200,7 +186,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// (see below). Recall that a default impl is not itself an impl, but rather a
// set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait {
- predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id)));
+ predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id)));
}
// Collect the region predicates that were declared inline as
@@ -333,8 +319,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// in trait checking. See `setup_constraining_predicates`
// for details.
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
- let self_ty = tcx.type_of(def_id).subst_identity();
- let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity);
+ let self_ty = tcx.type_of(def_id).instantiate_identity();
+ let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
cgp::setup_constraining_predicates(
tcx,
&mut predicates,
@@ -354,21 +340,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
};
debug!(?lifetimes);
- let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
- .map(|(arg, dup)| {
- let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
- (**arg, dup)
- })
- .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
- .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
-
- compute_bidirectional_outlives_predicates(
- tcx,
- def_id,
- lifetime_mapping,
- generics,
- &mut predicates,
- );
+ compute_bidirectional_outlives_predicates(tcx, &generics.params, &mut predicates);
debug!(?predicates);
}
@@ -382,39 +354,28 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
/// enforce that these lifetimes stay in sync.
fn compute_bidirectional_outlives_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- item_def_id: LocalDefId,
- lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
- generics: &Generics,
+ opaque_own_params: &[ty::GenericParamDef],
predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
) {
- let icx = ItemCtxt::new(tcx, item_def_id);
-
- for (arg, (dup_def, name, span)) in lifetime_mapping {
- let orig_region = icx.astconv().ast_region_to_region(&arg, None);
- if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
- // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
- // show up in the opaque's parent's substs.
- continue;
+ for param in opaque_own_params {
+ let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
+ if let ty::ReEarlyBound(..) = *orig_lifetime {
+ let dup_lifetime = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name },
+ );
+ let span = tcx.def_span(param.def_id);
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
+ .to_predicate(tcx),
+ span,
+ ));
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
+ .to_predicate(tcx),
+ span,
+ ));
}
-
- let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
-
- let dup_region = ty::Region::new_early_bound(
- tcx,
- ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
- );
-
- predicates.push((
- ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
- .to_predicate(tcx),
- span,
- ));
-
- predicates.push((
- ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
- .to_predicate(tcx),
- span,
- ));
}
}
@@ -493,20 +454,20 @@ pub(super) fn explicit_predicates_of<'tcx>(
// Remove bounds on associated types from the predicates, they will be
// returned by `explicit_item_bounds`.
let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
- let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let is_assoc_item_ty = |ty: Ty<'tcx>| {
// For a predicate from a where clause to become a bound on an
// associated type:
- // * It must use the identity substs of the item.
+ // * It must use the identity args of the item.
// * We're in the scope of the trait, so we can't name any
// parameters of the GAT. That means that all we need to
- // check are that the substs of the projection are the
- // identity substs of the trait.
+ // check are that the args of the projection are the
+ // identity args of the trait.
// * It must be an associated type for this trait (*not* a
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
- projection.substs == trait_identity_substs
+ projection.args == trait_identity_args
// FIXME(return_type_notation): This check should be more robust
&& !tcx.is_impl_trait_in_trait(projection.def_id)
&& tcx.associated_item(projection.def_id).container_id(tcx)
@@ -757,6 +718,7 @@ pub(super) fn type_param_predicates(
ItemKind::Fn(.., generics, _)
| ItemKind::Impl(&hir::Impl { generics, .. })
| ItemKind::TyAlias(_, generics)
+ | ItemKind::Const(_, generics, _)
| ItemKind::OpaqueTy(&OpaqueTy {
generics,
origin: hir::OpaqueTyOrigin::TyAlias { .. },
@@ -770,8 +732,7 @@ pub(super) fn type_param_predicates(
if param_id == item_hir_id {
let identity_trait_ref =
ty::TraitRef::identity(tcx, item_def_id.to_def_id());
- extend =
- Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
+ extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
}
generics
}
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index acd0bcd8e..6dd0c840d 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -137,12 +137,6 @@ enum Scope<'a> {
s: ScopeRef<'a>,
},
- /// A scope which either determines unspecified lifetimes or errors
- /// on them (e.g., due to ambiguity).
- Elision {
- s: ScopeRef<'a>,
- },
-
/// Use a specific lifetime (if `Some`) or leave it unset (to be
/// inferred in a function body or potentially error outside one),
/// for the default choice of lifetime in a trait object type.
@@ -211,7 +205,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
Scope::Body { id, s: _ } => {
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
}
- Scope::Elision { s: _ } => f.debug_struct("Elision").field("s", &"..").finish(),
Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
.debug_struct("ObjectLifetimeDefault")
.field("lifetime", lifetime)
@@ -325,9 +318,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
break (vec![], BinderScopeType::Normal);
}
- Scope::Elision { s, .. }
- | Scope::ObjectLifetimeDefault { s, .. }
- | Scope::AnonConstBoundary { s } => {
+ Scope::ObjectLifetimeDefault { s, .. } | Scope::AnonConstBoundary { s } => {
scope = s;
}
@@ -526,16 +517,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::ForeignMod { .. }
+ | hir::ItemKind::Static(..)
| hir::ItemKind::GlobalAsm(..) => {
// These sorts of items have no lifetime parameters at all.
intravisit::walk_item(self, item);
}
- hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
- // No lifetime parameters, but implied 'static.
- self.with(Scope::Elision { s: self.scope }, |this| {
- intravisit::walk_item(this, item)
- });
- }
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
@@ -596,6 +582,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
})
}
hir::ItemKind::TyAlias(_, generics)
+ | hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::Enum(_, generics)
| hir::ItemKind::Struct(_, generics)
| hir::ItemKind::Union(_, generics)
@@ -603,21 +590,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
- let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
- self.record_late_bound_vars(item.hir_id(), vec![]);
- let scope = Scope::Binder {
- hir_id: item.hir_id(),
- bound_vars,
- scope_type: BinderScopeType::Normal,
- s: self.scope,
- where_bound_origin: None,
- };
- self.with(scope, |this| {
- let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| {
- intravisit::walk_item(this, item);
- });
- });
+ self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
}
}
}
@@ -727,12 +700,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// Elided lifetimes are not allowed in non-return
// position impl Trait
let scope = Scope::TraitRefBoundary { s: self.scope };
- self.with(scope, |this| {
- let scope = Scope::Elision { s: this.scope };
- this.with(scope, |this| {
- intravisit::walk_item(this, opaque_ty);
- })
- });
+ self.with(scope, |this| intravisit::walk_item(this, opaque_ty));
return;
}
@@ -749,9 +717,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// `fn foo<'a>() -> MyAnonTy<'a> { ... }`
// ^ ^this gets resolved in the current scope
for lifetime in lifetimes {
- let hir::GenericArg::Lifetime(lifetime) = lifetime else {
- continue
- };
+ let hir::GenericArg::Lifetime(lifetime) = lifetime else { continue };
self.visit_lifetime(lifetime);
// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
@@ -759,12 +725,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
- let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
- continue
- };
- let Some(def_id) = def_id.as_local() else {
- continue
- };
+ let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue };
+ let Some(def_id) = def_id.as_local() else { continue };
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.tcx.hir().parent_id(hir_id);
@@ -801,39 +763,24 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
use self::hir::TraitItemKind::*;
match trait_item.kind {
Fn(_, _) => {
- self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
+ self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
intravisit::walk_trait_item(this, trait_item)
});
}
Type(bounds, ty) => {
- let generics = &trait_item.generics;
- let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
- self.record_late_bound_vars(trait_item.hir_id(), vec![]);
- let scope = Scope::Binder {
- hir_id: trait_item.hir_id(),
- bound_vars,
- s: self.scope,
- scope_type: BinderScopeType::Normal,
- where_bound_origin: None,
- };
- self.with(scope, |this| {
- let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| {
- this.visit_generics(generics);
- for bound in bounds {
- this.visit_param_bound(bound);
- }
- if let Some(ty) = ty {
- this.visit_ty(ty);
- }
- })
- });
- }
- Const(_, _) => {
- // Only methods and types support generics.
- assert!(trait_item.generics.params.is_empty());
- intravisit::walk_trait_item(self, trait_item);
+ self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
+ this.visit_generics(&trait_item.generics);
+ for bound in bounds {
+ this.visit_param_bound(bound);
+ }
+ if let Some(ty) = ty {
+ this.visit_ty(ty);
+ }
+ })
}
+ Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
+ intravisit::walk_trait_item(this, trait_item)
+ }),
}
}
@@ -841,34 +788,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
use self::hir::ImplItemKind::*;
match impl_item.kind {
- Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
+ Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
+ intravisit::walk_impl_item(this, impl_item)
+ }),
+ Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
+ this.visit_generics(impl_item.generics);
+ this.visit_ty(ty);
+ }),
+ Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item)
}),
- Type(ty) => {
- let generics = &impl_item.generics;
- let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
- generics.params.iter().map(ResolvedArg::early).collect();
- self.record_late_bound_vars(impl_item.hir_id(), vec![]);
- let scope = Scope::Binder {
- hir_id: impl_item.hir_id(),
- bound_vars,
- s: self.scope,
- scope_type: BinderScopeType::Normal,
- where_bound_origin: None,
- };
- self.with(scope, |this| {
- let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| {
- this.visit_generics(generics);
- this.visit_ty(ty);
- })
- });
- }
- Const(_, _) => {
- // Only methods and types support generics.
- assert!(impl_item.generics.params.is_empty());
- intravisit::walk_impl_item(self, impl_item);
- }
}
}
@@ -1204,6 +1133,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
self.with(scope, walk);
}
+ fn visit_early<F>(&mut self, hir_id: hir::HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
+ where
+ F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
+ {
+ let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
+ self.record_late_bound_vars(hir_id, vec![]);
+ let scope = Scope::Binder {
+ hir_id,
+ bound_vars,
+ s: self.scope,
+ scope_type: BinderScopeType::Normal,
+ where_bound_origin: None,
+ };
+ self.with(scope, |this| {
+ let scope = Scope::TraitRefBoundary { s: this.scope };
+ this.with(scope, walk)
+ });
+ }
+
#[instrument(level = "debug", skip(self))]
fn resolve_lifetime_ref(
&mut self,
@@ -1299,8 +1247,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
scope = s;
}
- Scope::Elision { s, .. }
- | Scope::ObjectLifetimeDefault { s, .. }
+ Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
| Scope::AnonConstBoundary { s } => {
@@ -1363,7 +1310,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Root { .. } => break,
Scope::Binder { s, .. }
| Scope::Body { s, .. }
- | Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
@@ -1415,8 +1361,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
scope = s;
}
- Scope::Elision { s, .. }
- | Scope::ObjectLifetimeDefault { s, .. }
+ Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
scope = s;
@@ -1489,7 +1434,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Root { .. } => break,
Scope::Binder { s, .. }
| Scope::Body { s, .. }
- | Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
@@ -1536,7 +1480,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
DefKind::Struct
| DefKind::Union
| DefKind::Enum
- | DefKind::TyAlias
+ | DefKind::TyAlias { .. }
| DefKind::Trait,
def_id,
) if depth == 0 => Some(def_id),
@@ -1570,7 +1514,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Body { .. } => break true,
Scope::Binder { s, .. }
- | Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. }
@@ -1727,7 +1670,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
},
));
bound_vars
- .extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
+ .extend(self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars());
bound_vars
} else {
self.tcx.sess.delay_span_bug(
@@ -1838,14 +1781,20 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
output: Option<&'tcx hir::Ty<'tcx>>,
in_closure: bool,
) {
- self.with(Scope::Elision { s: self.scope }, |this| {
- for input in inputs {
- this.visit_ty(input);
- }
- if !in_closure && let Some(output) = output {
- this.visit_ty(output);
- }
- });
+ self.with(
+ Scope::ObjectLifetimeDefault {
+ lifetime: Some(ResolvedArg::StaticLifetime),
+ s: self.scope,
+ },
+ |this| {
+ for input in inputs {
+ this.visit_ty(input);
+ }
+ if !in_closure && let Some(output) = output {
+ this.visit_ty(output);
+ }
+ },
+ );
if in_closure && let Some(output) = output {
self.visit_ty(output);
}
@@ -1865,7 +1814,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
scope = s;
}
- Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
+ Scope::Root { .. } => break ResolvedArg::StaticLifetime,
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
@@ -2041,15 +1990,15 @@ fn is_late_bound_map(
hir::TyKind::Path(hir::QPath::Resolved(
None,
- hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
+ hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span },
)) => {
// See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
- // substs to be unconstrained.
+ // args to be unconstrained.
let generics = self.tcx.generics_of(alias_def);
let mut walker = ConstrainedCollectorPostAstConv {
arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
};
- walker.visit_ty(self.tcx.type_of(alias_def).subst_identity());
+ walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
match segments.last() {
Some(hir::PathSegment { args: Some(args), .. }) => {
@@ -2063,8 +2012,7 @@ fn is_late_bound_map(
tcx.sess.delay_span_bug(
*span,
format!(
- "Incorrect generic arg count for alias {:?}",
- alias_def
+ "Incorrect generic arg count for alias {alias_def:?}"
),
);
None
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3755342ae..2bbdbe3a1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -3,7 +3,6 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirId;
use rustc_middle::ty::print::with_forced_trimmed_paths;
-use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::Ident;
@@ -157,7 +156,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
- format!("unable to find type-dependent def for {:?}", parent_node_id),
+ format!("unable to find type-dependent def for {parent_node_id:?}"),
);
};
let idx = segment
@@ -198,14 +197,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
} else {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
- format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
+ format!("unable to find const parent for {hir_id} in pat {pat:?}"),
);
}
}
_ => {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
- format!("unexpected const parent path {:?}", parent_node),
+ format!("unexpected const parent path {parent_node:?}"),
);
}
};
@@ -338,8 +337,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
let output = match tcx.hir().get(hir_id) {
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
TraitItemKind::Const(ty, body_id) => body_id
.and_then(|body_id| {
@@ -363,8 +362,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ImplItem(item) => match item.kind {
ImplItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
ImplItemKind::Const(ty, body_id) => {
if is_suggestable_infer_ty(ty) {
@@ -405,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
icx.to_ty(ty)
}
}
- ItemKind::Const(ty, body_id) => {
+ ItemKind::Const(ty, _, body_id) => {
if is_suggestable_infer_ty(ty) {
infer_placeholder_type(
tcx, def_id, body_id, ty.span, item.ident, "constant",
@@ -426,13 +425,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
_ => icx.to_ty(*self_ty),
},
ItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
let def = tcx.adt_def(def_id);
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_adt(tcx, def, substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_adt(tcx, def, args)
}
ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
@@ -472,8 +471,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ForeignItem(foreign_item) => match foreign_item.kind {
ForeignItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
ForeignItemKind::Static(t, _) => icx.to_ty(t),
ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
@@ -481,11 +480,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
VariantData::Unit(..) | VariantData::Struct(..) => {
- tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity()
+ tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity()
}
VariantData::Tuple(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id);
+ Ty::new_fn_def(tcx, def_id.to_def_id(), args)
}
},
@@ -498,8 +497,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::ConstBlock(_) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- substs.as_inline_const().ty()
+ let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
+ args.as_inline_const().ty()
}
Node::GenericParam(param) => match &param.kind {
@@ -545,7 +544,7 @@ fn infer_placeholder_type<'a>(
if let Some(ty) = ty.make_suggestable(tcx, false) {
err.span_suggestion(
span,
- format!("provide a type for the {item}", item = kind),
+ format!("provide a type for the {kind}"),
format!("{colon} {ty}"),
Applicability::MachineApplicable,
);
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 35882ad35..5591fa6f2 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -59,7 +59,7 @@ struct ParameterCollector {
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
- ty::Alias(ty::Projection | ty::Inherent, ..) if !self.include_nonconstraining => {
+ ty::Alias(..) if !self.include_nonconstraining => {
// projections are not injective
return ControlFlow::Continue(());
}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c2d2e5f7e..9471ad9ca 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -216,7 +216,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
"parameters",
self.missing_type_params
.iter()
- .map(|n| format!("`{}`", n))
+ .map(|n| format!("`{n}`"))
.collect::<Vec<_>>()
.join(", "),
);
@@ -918,3 +918,12 @@ pub struct UnusedAssociatedTypeBounds {
#[suggestion(code = "")]
pub span: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_assoc_bound_on_const)]
+#[note]
+pub struct AssocBoundOnConst {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'static str,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index f1765174d..ca7679cfb 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -130,7 +130,7 @@ fn diagnostic_hir_wf_check<'tcx>(
hir::Node::Item(item) => match item.kind {
hir::ItemKind::TyAlias(ty, _)
| hir::ItemKind::Static(ty, _, _)
- | hir::ItemKind::Const(ty, _) => vec![ty],
+ | hir::ItemKind::Const(ty, _, _) => vec![ty],
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
Some(t) => t
.path
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 5526dd4b0..788121f7a 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -14,7 +14,7 @@ use min_specialization::check_min_specialization;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::{Span, Symbol};
@@ -51,7 +51,7 @@ mod min_specialization;
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
/// // ^ 'a is unused and appears in assoc type, error
/// ```
-fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
+fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
let min_specialization = tcx.features().min_specialization;
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
@@ -70,22 +70,21 @@ pub fn provide(providers: &mut Providers) {
fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
// Every lifetime used in an associated type must be constrained.
- let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
+ let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
if impl_self_ty.references_error() {
// Don't complain about unconstrained type params when self ty isn't known due to errors.
// (#36836)
tcx.sess.delay_span_bug(
tcx.def_span(impl_def_id),
format!(
- "potentially unconstrained type parameters weren't evaluated: {:?}",
- impl_self_ty,
+ "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
),
);
return;
}
let impl_generics = tcx.generics_of(impl_def_id);
let impl_predicates = tcx.predicates_of(impl_def_id);
- let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity);
+ let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
cgp::identify_constrained_generic_params(
@@ -104,25 +103,12 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
match item.kind {
ty::AssocKind::Type => {
if item.defaultness(tcx).has_value() {
- cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
+ cgp::parameters_for(&tcx.type_of(def_id).instantiate_identity(), true)
} else {
vec![]
}
}
- ty::AssocKind::Fn => {
- if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
- && item.defaultness(tcx).has_value()
- && tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
- && let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
- {
- table.values().copied().flat_map(|ty| {
- cgp::parameters_for(&ty.subst_identity(), true)
- }).collect()
- } else {
- vec![]
- }
- }
- ty::AssocKind::Const => vec![],
+ ty::AssocKind::Fn | ty::AssocKind::Const => vec![],
}
})
.collect();
@@ -193,7 +179,7 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
kind,
name
);
- err.span_label(span, format!("unconstrained {} parameter", kind));
+ err.span_label(span, format!("unconstrained {kind} parameter"));
if kind == "const" {
err.note(
"expressions using a const parameter must map each value to a distinct output value",
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index c64fb469b..3760195a5 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -14,15 +14,15 @@
//! To enforce this requirement on specializations we take the following
//! approach:
//!
-//! 1. Match up the substs for `impl2` so that the implemented trait and
+//! 1. Match up the args for `impl2` so that the implemented trait and
//! self-type match those for `impl1`.
-//! 2. Check for any direct use of `'static` in the substs of `impl2`.
+//! 2. Check for any direct use of `'static` in the args of `impl2`.
//! 3. Check that all of the generic parameters of `impl1` occur at most once
-//! in the *unconstrained* substs for `impl2`. A parameter is constrained if
+//! in the *unconstrained* args for `impl2`. A parameter is constrained if
//! its value is completely determined by an associated type projection
//! predicate.
//! 4. Check that all predicates on `impl1` either exist on `impl2` (after
-//! matching substs), or are well-formed predicates for the trait's type
+//! matching args), or are well-formed predicates for the trait's type
//! arguments.
//!
//! ## Example
@@ -74,13 +74,13 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::specialization_graph::Node;
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
+use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};
pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
@@ -113,20 +113,20 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
let span = tcx.def_span(impl1_def_id);
check_has_items(tcx, impl1_def_id, impl2_node, span);
- if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
+ if let Ok((impl1_args, impl2_args)) = get_impl_args(tcx, impl1_def_id, impl2_node) {
let impl2_def_id = impl2_node.def_id();
- debug!(?impl2_def_id, ?impl2_substs);
+ debug!(?impl2_def_id, ?impl2_args);
- let parent_substs = if impl2_node.is_from_trait() {
- impl2_substs.to_vec()
+ let parent_args = if impl2_node.is_from_trait() {
+ impl2_args.to_vec()
} else {
- unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
+ unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
};
check_constness(tcx, impl1_def_id, impl2_node, span);
- check_static_lifetimes(tcx, &parent_substs, span);
- check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
- check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+ check_static_lifetimes(tcx, &parent_args, span);
+ check_duplicate_params(tcx, impl1_args, &parent_args, span);
+ check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span);
}
}
@@ -167,23 +167,23 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
/// ```
///
/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
-fn get_impl_substs(
+fn get_impl_args(
tcx: TyCtxt<'_>,
impl1_def_id: LocalDefId,
impl2_node: Node,
-) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> {
+) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
let param_env = tcx.param_env(impl1_def_id);
let impl1_span = tcx.def_span(impl1_def_id);
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
- let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
- let impl2_substs = translate_substs_with_cause(
+ let impl1_args = GenericArgs::identity_for_item(tcx, impl1_def_id);
+ let impl2_args = translate_args_with_cause(
infcx,
param_env,
impl1_def_id.to_def_id(),
- impl1_substs,
+ impl1_args,
impl2_node,
|_, span| {
traits::ObligationCause::new(
@@ -203,12 +203,12 @@ fn get_impl_substs(
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
- let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+ let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
let span = tcx.def_span(impl1_def_id);
let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
return Err(guar);
};
- Ok((impl1_substs, impl2_substs))
+ Ok((impl1_args, impl2_args))
}
/// Returns a list of all of the unconstrained subst of the given impl.
@@ -217,17 +217,17 @@ fn get_impl_substs(
///
/// impl<'a, T, I> ... where &'a I: IntoIterator<Item=&'a T>
///
-/// This would return the substs corresponding to `['a, I]`, because knowing
+/// This would return the args corresponding to `['a, I]`, because knowing
/// `'a` and `I` determines the value of `T`.
-fn unconstrained_parent_impl_substs<'tcx>(
+fn unconstrained_parent_impl_args<'tcx>(
tcx: TyCtxt<'tcx>,
impl_def_id: DefId,
- impl_substs: SubstsRef<'tcx>,
+ impl_args: GenericArgsRef<'tcx>,
) -> Vec<GenericArg<'tcx>> {
let impl_generic_predicates = tcx.predicates_of(impl_def_id);
let mut unconstrained_parameters = FxHashSet::default();
let mut constrained_params = FxHashSet::default();
- let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity);
+ let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
// Unfortunately the functions in `constrained_generic_parameters` don't do
// what we want here. We want only a list of constrained parameters while
@@ -255,7 +255,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
}
}
- impl_substs
+ impl_args
.iter()
.enumerate()
.filter(|&(idx, _)| !constrained_params.contains(&(idx as u32)))
@@ -264,7 +264,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
}
/// Check that parameters of the derived impl don't occur more than once in the
-/// equated substs of the base impl.
+/// equated args of the base impl.
///
/// For example forbid the following:
///
@@ -280,21 +280,21 @@ fn unconstrained_parent_impl_substs<'tcx>(
/// impl<T> Tr<T> for Vec<T> { }
/// ```
///
-/// The substs for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
-/// but `S` is constrained in the parent impl, so `parent_substs` is only
+/// The args for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
+/// but `S` is constrained in the parent impl, so `parent_args` is only
/// `[Vec<T>]`. This means we allow this impl.
fn check_duplicate_params<'tcx>(
tcx: TyCtxt<'tcx>,
- impl1_substs: SubstsRef<'tcx>,
- parent_substs: &Vec<GenericArg<'tcx>>,
+ impl1_args: GenericArgsRef<'tcx>,
+ parent_args: &Vec<GenericArg<'tcx>>,
span: Span,
) {
- let mut base_params = cgp::parameters_for(parent_substs, true);
+ let mut base_params = cgp::parameters_for(parent_args, true);
base_params.sort_by_key(|param| param.0);
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
- let param = impl1_substs[duplicate.0 as usize];
+ let param = impl1_args[duplicate.0 as usize];
tcx.sess
- .struct_span_err(span, format!("specializing impl repeats parameter `{}`", param))
+ .struct_span_err(span, format!("specializing impl repeats parameter `{param}`"))
.emit();
}
}
@@ -309,10 +309,10 @@ fn check_duplicate_params<'tcx>(
/// ```
fn check_static_lifetimes<'tcx>(
tcx: TyCtxt<'tcx>,
- parent_substs: &Vec<GenericArg<'tcx>>,
+ parent_args: &Vec<GenericArg<'tcx>>,
span: Span,
) {
- if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) {
+ if tcx.any_free_region_meets(parent_args, |r| r.is_static()) {
tcx.sess.emit_err(errors::StaticSpecialize { span });
}
}
@@ -331,14 +331,14 @@ fn check_static_lifetimes<'tcx>(
fn check_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
impl1_def_id: LocalDefId,
- impl1_substs: SubstsRef<'tcx>,
+ impl1_args: GenericArgsRef<'tcx>,
impl2_node: Node,
- impl2_substs: SubstsRef<'tcx>,
+ impl2_args: GenericArgsRef<'tcx>,
span: Span,
) {
let impl1_predicates: Vec<_> = traits::elaborate(
tcx,
- tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).into_iter(),
+ tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_args).into_iter(),
)
.collect();
@@ -350,7 +350,7 @@ fn check_predicates<'tcx>(
traits::elaborate(
tcx,
tcx.predicates_of(impl2_node.def_id())
- .instantiate(tcx, impl2_substs)
+ .instantiate(tcx, impl2_args)
.into_iter()
.map(|(c, _s)| c.as_predicate()),
)
@@ -385,7 +385,7 @@ fn check_predicates<'tcx>(
.map(|(c, _span)| c.as_predicate());
// Include the well-formed predicates of the type parameters of the impl.
- for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
+ for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
let infcx = &tcx.infer_ctxt().build();
let obligations =
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
@@ -431,45 +431,13 @@ fn check_predicates<'tcx>(
///
/// So we make that check in this function and try to raise a helpful error message.
fn trait_predicates_eq<'tcx>(
- tcx: TyCtxt<'tcx>,
+ _tcx: TyCtxt<'tcx>,
predicate1: ty::Predicate<'tcx>,
predicate2: ty::Predicate<'tcx>,
- span: Span,
+ _span: Span,
) -> bool {
- let pred1_kind = predicate1.kind().skip_binder();
- let pred2_kind = predicate2.kind().skip_binder();
- let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) {
- (
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)),
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)),
- ) => (pred1, pred2),
- // Just use plain syntactic equivalence if either of the predicates aren't
- // trait predicates or have bound vars.
- _ => return predicate1 == predicate2,
- };
-
- let predicates_equal_modulo_constness = {
- let pred1_unconsted =
- ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred1 };
- let pred2_unconsted =
- ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred2 };
- pred1_unconsted == pred2_unconsted
- };
-
- if !predicates_equal_modulo_constness {
- return false;
- }
-
- // Check that the predicate on the specializing impl is at least as const as
- // the one on the base.
- match (trait_pred2.constness, trait_pred1.constness) {
- (ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => {
- tcx.sess.emit_err(errors::MissingTildeConst { span });
- }
- _ => {}
- }
-
- true
+ // FIXME(effects)
+ predicate1 == predicate2
}
#[instrument(level = "debug", skip(tcx))]
@@ -482,7 +450,6 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
// items.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
- constness: _,
polarity: _,
})) => {
if !matches!(
@@ -523,7 +490,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
}
_ => {
tcx.sess
- .struct_span_err(span, format!("cannot specialize on predicate `{}`", predicate))
+ .struct_span_err(span, format!("cannot specialize on predicate `{predicate}`"))
.emit();
}
}
@@ -536,7 +503,6 @@ fn trait_predicate_kind<'tcx>(
match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
- constness: _,
polarity: _,
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index a68832d96..4f95174f8 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -99,23 +99,20 @@ use rustc_errors::ErrorGuaranteed;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
-use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::middle;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util;
-use rustc_session::{config::EntryFnType, parse::feature_err};
-use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_session::parse::feature_err;
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
-
-use std::ops::Not;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
use astconv::{AstConv, OnlySelfBounds};
use bounds::Bounds;
+use rustc_hir::def::DefKind;
fluent_messages! { "../messages.ftl" }
@@ -176,271 +173,11 @@ fn require_same_types<'tcx>(
}
}
-fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
- let main_fnsig = tcx.fn_sig(main_def_id).subst_identity();
- let main_span = tcx.def_span(main_def_id);
-
- fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
- if let Some(local_def_id) = def_id.as_local() {
- let hir_type = tcx.type_of(local_def_id).subst_identity();
- if !matches!(hir_type.kind(), ty::FnDef(..)) {
- span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
- }
- local_def_id
- } else {
- CRATE_DEF_ID
- }
- }
-
- fn main_fn_generics_params_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
- if !def_id.is_local() {
- return None;
- }
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- match tcx.hir().find(hir_id) {
- Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
- generics.params.is_empty().not().then_some(generics.span)
- }
- _ => {
- span_bug!(tcx.def_span(def_id), "main has a non-function type");
- }
- }
- }
-
- fn main_fn_where_clauses_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
- if !def_id.is_local() {
- return None;
- }
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- match tcx.hir().find(hir_id) {
- Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
- Some(generics.where_clause_span)
- }
- _ => {
- span_bug!(tcx.def_span(def_id), "main has a non-function type");
- }
- }
- }
-
- fn main_fn_asyncness_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
- if !def_id.is_local() {
- return None;
- }
- Some(tcx.def_span(def_id))
- }
-
- fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
- if !def_id.is_local() {
- return None;
- }
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- match tcx.hir().find(hir_id) {
- Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => {
- Some(fn_sig.decl.output.span())
- }
- _ => {
- span_bug!(tcx.def_span(def_id), "main has a non-function type");
- }
- }
- }
-
- let mut error = false;
- let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
- let main_fn_generics = tcx.generics_of(main_def_id);
- let main_fn_predicates = tcx.predicates_of(main_def_id);
- if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
- let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
- tcx.sess.emit_err(errors::MainFunctionGenericParameters {
- span: generics_param_span.unwrap_or(main_span),
- label_span: generics_param_span,
- });
- error = true;
- } else if !main_fn_predicates.predicates.is_empty() {
- // generics may bring in implicit predicates, so we skip this check if generics is present.
- let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
- tcx.sess.emit_err(errors::WhereClauseOnMain {
- span: generics_where_clauses_span.unwrap_or(main_span),
- generics_span: generics_where_clauses_span,
- });
- error = true;
- }
-
- let main_asyncness = tcx.asyncness(main_def_id);
- if let hir::IsAsync::Async = main_asyncness {
- let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
- tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
- error = true;
- }
-
- for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
- tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
- error = true;
- }
-
- if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
- // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
- && !tcx.sess.target.is_like_wasm
- && !tcx.sess.opts.actually_rustdoc
- {
- tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
- error = true;
- }
-
- if error {
- return;
- }
-
- // Main should have no WC, so empty param env is OK here.
- let param_env = ty::ParamEnv::empty();
- let expected_return_type;
- if let Some(term_did) = tcx.lang_items().termination() {
- let return_ty = main_fnsig.output();
- let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
- if !return_ty.bound_vars().is_empty() {
- tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
- error = true;
- }
- let return_ty = return_ty.skip_binder();
- let infcx = tcx.infer_ctxt().build();
- let cause = traits::ObligationCause::new(
- return_ty_span,
- main_diagnostics_def_id,
- ObligationCauseCode::MainFunctionType,
- );
- let ocx = traits::ObligationCtxt::new(&infcx);
- let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
- ocx.register_bound(cause, param_env, norm_return_ty, term_did);
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors);
- error = true;
- }
- // now we can take the return type of the given main function
- expected_return_type = main_fnsig.output();
- } else {
- // standard () main return type
- expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
- }
-
- if error {
- return;
- }
-
- let se_ty = Ty::new_fn_ptr(
- tcx,
- expected_return_type.map_bound(|expected_return_type| {
- tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
- }),
- );
-
- require_same_types(
- tcx,
- &ObligationCause::new(
- main_span,
- main_diagnostics_def_id,
- ObligationCauseCode::MainFunctionType,
- ),
- param_env,
- se_ty,
- Ty::new_fn_ptr(tcx, main_fnsig),
- );
-}
-fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
- let start_def_id = start_def_id.expect_local();
- let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
- let start_span = tcx.def_span(start_def_id);
- let start_t = tcx.type_of(start_def_id).subst_identity();
- match start_t.kind() {
- ty::FnDef(..) => {
- if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
- if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
- let mut error = false;
- if !generics.params.is_empty() {
- tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
- error = true;
- }
- if generics.has_where_clause_predicates {
- tcx.sess.emit_err(errors::StartFunctionWhere {
- span: generics.where_clause_span,
- });
- error = true;
- }
- if let hir::IsAsync::Async = sig.header.asyncness {
- let span = tcx.def_span(it.owner_id);
- tcx.sess.emit_err(errors::StartAsync { span: span });
- error = true;
- }
-
- let attrs = tcx.hir().attrs(start_id);
- for attr in attrs {
- if attr.has_name(sym::track_caller) {
- tcx.sess.emit_err(errors::StartTrackCaller {
- span: attr.span,
- start: start_span,
- });
- error = true;
- }
- if attr.has_name(sym::target_feature)
- // Calling functions with `#[target_feature]` is
- // not unsafe on WASM, see #84988
- && !tcx.sess.target.is_like_wasm
- && !tcx.sess.opts.actually_rustdoc
- {
- tcx.sess.emit_err(errors::StartTargetFeature {
- span: attr.span,
- start: start_span,
- });
- error = true;
- }
- }
-
- if error {
- return;
- }
- }
- }
-
- let se_ty = Ty::new_fn_ptr(
- tcx,
- ty::Binder::dummy(tcx.mk_fn_sig(
- [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
- tcx.types.isize,
- false,
- hir::Unsafety::Normal,
- Abi::Rust,
- )),
- );
-
- require_same_types(
- tcx,
- &ObligationCause::new(
- start_span,
- start_def_id,
- ObligationCauseCode::StartFunctionType,
- ),
- ty::ParamEnv::empty(), // start should not have any where bounds.
- se_ty,
- Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()),
- );
- }
- _ => {
- span_bug!(start_span, "start has a non-function type: found `{}`", start_t);
- }
- }
-}
-
-fn check_for_entry_fn(tcx: TyCtxt<'_>) {
- match tcx.entry_fn(()) {
- Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
- Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
- _ => {}
- }
-}
-
pub fn provide(providers: &mut Providers) {
collect::provide(providers);
coherence::provide(providers);
check::provide(providers);
+ check_unused::provide(providers);
variance::provide(providers);
outlives::provide(providers);
impl_wf_check::provide(providers);
@@ -500,8 +237,18 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
- check_unused::check_crate(tcx);
- check_for_entry_fn(tcx);
+ // FIXME: Remove this when we implement creating `DefId`s
+ // for anon constants during their parents' typeck.
+ // Typeck all body owners in parallel will produce queries
+ // cycle errors because it may typeck on anon constants directly.
+ tcx.hir().par_body_owners(|item_def_id| {
+ let def_kind = tcx.def_kind(item_def_id);
+ if !matches!(def_kind, DefKind::AnonConst) {
+ tcx.ensure().typeck(item_def_id);
+ }
+ });
+
+ tcx.ensure().check_unused_traits(());
if let Some(reported) = tcx.sess.has_errors() { Err(reported) } else { Ok(()) }
}
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 71dca918f..c17925471 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -46,7 +46,7 @@ pub(super) fn infer_predicates(
// For field of type &'a T (reference) or Adt
// (struct/enum/union) there will be outlive
// requirements for adt_def.
- let field_ty = tcx.type_of(field_def.did).subst_identity();
+ let field_ty = tcx.type_of(field_def.did).instantiate_identity();
let field_span = tcx.def_span(field_def.did);
insert_required_predicates_to_be_wf(
tcx,
@@ -117,7 +117,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// can load the current set of inferred and explicit
// predicates from `global_inferred_outlives` and filter the
// ones that are TypeOutlives.
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
// First check the inferred predicates
//
// Example 1:
@@ -146,7 +146,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// get `T: 'a` (or `predicate`):
let predicate = unsubstituted_predicates
.rebind(*unsubstituted_predicate)
- .subst(tcx, substs);
+ .instantiate(tcx, args);
insert_outlives_predicate(
tcx,
predicate.0,
@@ -159,11 +159,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// Check if the type has any explicit predicates that need
// to be added to `required_predicates`
- // let _: () = substs.region_at(0);
+ // let _: () = args.region_at(0);
check_explicit_predicates(
tcx,
def.did(),
- substs,
+ args,
required_predicates,
explicit_map,
None,
@@ -186,12 +186,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// predicates in `check_explicit_predicates` we
// need to ignore checking the explicit_map for
// Self type.
- let substs =
- ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().substs;
+ let args = ex_trait_ref.with_self_ty(tcx, tcx.types.usize).skip_binder().args;
check_explicit_predicates(
tcx,
ex_trait_ref.skip_binder().def_id,
- substs,
+ args,
required_predicates,
explicit_map,
Some(tcx.types.self_param),
@@ -206,7 +205,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
check_explicit_predicates(
tcx,
tcx.parent(obj.def_id),
- obj.substs,
+ obj.args,
required_predicates,
explicit_map,
None,
@@ -239,18 +238,18 @@ fn insert_required_predicates_to_be_wf<'tcx>(
fn check_explicit_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- substs: &[GenericArg<'tcx>],
+ args: &[GenericArg<'tcx>],
required_predicates: &mut RequiredPredicates<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
ignored_self_ty: Option<Ty<'tcx>>,
) {
debug!(
"check_explicit_predicates(def_id={:?}, \
- substs={:?}, \
+ args={:?}, \
explicit_map={:?}, \
required_predicates={:?}, \
ignored_self_ty={:?})",
- def_id, substs, explicit_map, required_predicates, ignored_self_ty,
+ def_id, args, explicit_map, required_predicates, ignored_self_ty,
);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
@@ -278,10 +277,10 @@ fn check_explicit_predicates<'tcx>(
// that is represented by the `dyn Trait`, not to the `X` type parameter
// (or any other generic parameter) declared on `MyStruct`.
//
- // Note that we do this check for self **before** applying `substs`. In the
- // case that `substs` come from a `dyn Trait` type, our caller will have
+ // Note that we do this check for self **before** applying `args`. In the
+ // case that `args` come from a `dyn Trait` type, our caller will have
// included `Self = usize` as the value for `Self`. If we were
- // to apply the substs, and not filter this predicate, we might then falsely
+ // to apply the args, and not filter this predicate, we might then falsely
// conclude that e.g., `X: 'x` was a reasonable inferred requirement.
//
// Another similar case is where we have an inferred
@@ -299,7 +298,7 @@ fn check_explicit_predicates<'tcx>(
continue;
}
- let predicate = explicit_predicates.rebind(*outlives_predicate).subst(tcx, substs);
+ let predicate = explicit_predicates.rebind(*outlives_predicate).instantiate(tcx, args);
debug!("predicate = {:?}", &predicate);
insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
}
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 48624cefe..be9d076bd 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -2,7 +2,7 @@ use hir::Node;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index c5c5f63a1..a6410c944 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -1,6 +1,6 @@
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, Region, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::Span;
use smallvec::smallvec;
use std::collections::BTreeMap;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index ee3457282..61b182b1b 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -360,9 +360,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
&[]
};
ret.extend(params.iter().filter_map(|p| {
- let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
- = p.kind
- else { return None };
+ let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } =
+ p.kind
+ else {
+ return None;
+ };
let hir::ParamName::Plain(name) = p.name else { return None };
Some(name.to_string())
}));
@@ -472,7 +474,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
verb
)
} else {
- format!("missing generics for {} `{}`", def_kind, def_path)
+ format!("missing generics for {def_kind} `{def_path}`")
}
}
@@ -576,6 +578,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
MissingTypesOrConsts { .. } => {
self.suggest_adding_type_and_const_args(err);
}
+ ExcessTypesOrConsts { .. } => {
+ // this can happen with `~const T` where T isn't a const_trait.
+ }
_ => unreachable!(),
}
}
@@ -597,7 +602,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let span = self.path_segment.ident.span;
// insert a suggestion of the form "Y<'a, 'b>"
- let sugg = format!("<{}>", suggested_args);
+ let sugg = format!("<{suggested_args}>");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(
@@ -622,7 +627,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg_suffix =
if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" };
- let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
+ let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
@@ -647,7 +652,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let span = self.path_segment.ident.span;
// insert a suggestion of the form "Y<T, U>"
- let sugg = format!("<{}>", suggested_args);
+ let sugg = format!("<{suggested_args}>");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(
@@ -680,7 +685,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg_suffix =
if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" };
- let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
+ let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
@@ -793,29 +798,36 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
num_trait_generics_except_self: usize,
) {
let sm = self.tcx.sess.source_map();
- let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return; };
+ let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else {
+ return;
+ };
if num_assoc_fn_excess_args != num_trait_generics_except_self {
return;
}
- let Some(gen_args) = self.gen_args.span_ext() else { return; };
- let Ok(generics) = sm.span_to_snippet(gen_args) else { return; };
- let Ok(rcvr) = sm.span_to_snippet(
- rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span)
- ) else { return; };
- let Ok(rest) =
- (match args {
- [] => Ok(String::new()),
- [arg] => sm.span_to_snippet(
- arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span),
- ),
- [first, .., last] => {
- let first_span =
- first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
- let last_span =
- last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
- sm.span_to_snippet(first_span.to(last_span))
- }
- }) else { return; };
+ let Some(gen_args) = self.gen_args.span_ext() else {
+ return;
+ };
+ let Ok(generics) = sm.span_to_snippet(gen_args) else {
+ return;
+ };
+ let Ok(rcvr) =
+ sm.span_to_snippet(rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span))
+ else {
+ return;
+ };
+ let Ok(rest) = (match args {
+ [] => Ok(String::new()),
+ [arg] => {
+ sm.span_to_snippet(arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span))
+ }
+ [first, .., last] => {
+ let first_span = first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
+ let last_span = last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
+ sm.span_to_snippet(first_span.to(last_span))
+ }
+ }) else {
+ return;
+ };
let comma = if args.len() > 0 { ", " } else { "" };
let trait_path = self.tcx.def_path_str(trait_def_id);
let method_name = self.tcx.item_name(self.def_id);
@@ -1015,7 +1027,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
.collect::<Vec<_>>()
.join(", ");
- format!(": {}", params)
+ format!(": {params}")
};
format!(
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 6f0afae1b..8a40509d7 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -6,8 +6,8 @@
use hir::def_id::{DefId, LocalDefId};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use super::terms::VarianceTerm::*;
use super::terms::*;
@@ -78,6 +78,11 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
}
}
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+ {
+ constraint_cx.build_constraints_for_item(def_id)
+ }
_ => {}
}
}
@@ -101,7 +106,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let inferred_start = self.terms_cx.inferred_starts[&def_id];
let current_item = &CurrentItem { inferred_start };
- match tcx.type_of(def_id).subst_identity().kind() {
+ let ty = tcx.type_of(def_id).instantiate_identity();
+
+ // The type as returned by `type_of` is the underlying type and generally not a weak projection.
+ // Therefore we need to check the `DefKind` first.
+ if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id)
+ && (lazy || ty.has_opaque_types())
+ {
+ self.add_constraints_from_ty(current_item, ty, self.covariant);
+ return;
+ }
+
+ match ty.kind() {
ty::Adt(def, _) => {
// Not entirely obvious: constraints on structs/enums do not
// affect the variance of their type parameters. See discussion
@@ -112,7 +128,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
for field in def.all_fields() {
self.add_constraints_from_ty(
current_item,
- tcx.type_of(field.did).subst_identity(),
+ tcx.type_of(field.did).instantiate_identity(),
self.covariant,
);
}
@@ -121,12 +137,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
ty::FnDef(..) => {
self.add_constraints_from_sig(
current_item,
- tcx.fn_sig(def_id).subst_identity(),
+ tcx.fn_sig(def_id).instantiate_identity(),
self.covariant,
);
}
ty::Error(_) => {}
+
_ => {
span_bug!(
tcx.def_span(def_id),
@@ -175,16 +192,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self, current))]
- fn add_constraints_from_invariant_substs(
+ fn add_constraints_from_invariant_args(
&mut self,
current: &CurrentItem,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
variance: VarianceTermPtr<'a>,
) {
// Trait are always invariant so we can take advantage of that.
let variance_i = self.invariant(variance);
- for k in substs {
+ for k in args {
match k.unpack() {
GenericArgKind::Lifetime(lt) => {
self.add_constraints_from_region(current, lt, variance_i)
@@ -248,12 +265,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
}
- ty::Adt(def, substs) => {
- self.add_constraints_from_substs(current, def.did(), substs, variance);
+ ty::Adt(def, args) => {
+ self.add_constraints_from_args(current, def.did(), args, variance);
+ }
+
+ ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
+ self.add_constraints_from_invariant_args(current, data.args, variance);
}
- ty::Alias(_, ref data) => {
- self.add_constraints_from_invariant_substs(current, data.substs, variance);
+ ty::Alias(ty::Weak, ref data) => {
+ self.add_constraints_from_args(current, data.def_id, data.args, variance);
}
ty::Dynamic(data, r, _) => {
@@ -261,9 +282,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_region(current, r, variance);
if let Some(poly_trait_ref) = data.principal() {
- self.add_constraints_from_invariant_substs(
+ self.add_constraints_from_invariant_args(
current,
- poly_trait_ref.skip_binder().substs,
+ poly_trait_ref.skip_binder().args,
variance,
);
}
@@ -305,20 +326,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a nominal type (enum, struct,
/// object, etc) appearing in a context with ambient variance `variance`
- fn add_constraints_from_substs(
+ fn add_constraints_from_args(
&mut self,
current: &CurrentItem,
def_id: DefId,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
variance: VarianceTermPtr<'a>,
) {
debug!(
- "add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
- def_id, substs, variance
+ "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})",
+ def_id, args, variance
);
// We don't record `inferred_starts` entries for empty generics.
- if substs.is_empty() {
+ if args.is_empty() {
return;
}
@@ -328,7 +349,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
(None, Some(self.tcx().variances_of(def_id)))
};
- for (i, k) in substs.iter().enumerate() {
+ for (i, k) in args.iter().enumerate() {
let variance_decl = if let Some(InferredIndex(start)) = local {
// Parameter on an item defined within current crate:
// variance not yet inferred, so return a symbolic
@@ -341,7 +362,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
};
let variance_i = self.xform(variance, variance_decl);
debug!(
- "add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
+ "add_constraints_from_args: variance_decl={:?} variance_i={:?}",
variance_decl, variance_i
);
match k.unpack() {
@@ -368,7 +389,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
match &c.kind() {
ty::ConstKind::Unevaluated(uv) => {
- self.add_constraints_from_invariant_substs(current, uv.substs, variance);
+ self.add_constraints_from_invariant_args(current, uv.args, variance);
}
_ => {}
}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 066e74491..d91d9fcbc 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,8 +7,8 @@ use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can
@@ -56,7 +56,14 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
let crate_map = tcx.crate_variances(());
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
}
- DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
+ {
+ // These are inferred.
+ let crate_map = tcx.crate_variances(());
+ return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
+ }
+ DefKind::OpaqueTy => {
return variance_of_opaque(tcx, item_def_id);
}
_ => {}
@@ -83,17 +90,17 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)]
- fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
+ fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
let child_variances = self.tcx.variances_of(def_id);
- for (a, v) in substs.iter().zip(child_variances) {
+ for (a, v) in args.iter().zip(child_variances) {
if *v != ty::Bivariant {
a.visit_with(self)?;
}
}
ControlFlow::Continue(())
} else {
- substs.visit_with(self)
+ args.visit_with(self)
}
}
}
@@ -110,18 +117,10 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
#[instrument(level = "trace", skip(self), ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
- ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ ty::Alias(_, ty::AliasTy { def_id, args, .. })
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
{
- self.visit_opaque(*def_id, substs)
- }
- // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
- // at all for RPITITs.
- ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if self.tcx.is_impl_trait_in_trait(*def_id)
- && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() =>
- {
- self.visit_opaque(*def_id, substs)
+ self.visit_opaque(*def_id, args)
}
_ => t.super_visit_with(self),
}
@@ -152,30 +151,29 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut collector =
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
- let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
- for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
+ let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
+ for (pred, _) in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) {
debug!(?pred);
- // We only ignore opaque type substs if the opaque type is the outermost type.
+ // We only ignore opaque type args if the opaque type is the outermost type.
// The opaque type may be nested within itself via recursion in e.g.
// type Foo<'a> = impl PartialEq<Foo<'a>>;
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate {
- trait_ref: ty::TraitRef { def_id: _, substs, .. },
- constness: _,
+ trait_ref: ty::TraitRef { def_id: _, args, .. },
polarity: _,
}) => {
- for subst in &substs[1..] {
+ for subst in &args[1..] {
subst.visit_with(&mut collector);
}
}
ty::ClauseKind::Projection(ty::ProjectionPredicate {
- projection_ty: ty::AliasTy { substs, .. },
+ projection_ty: ty::AliasTy { args, .. },
term,
}) => {
- for subst in &substs[1..] {
+ for subst in &args[1..] {
subst.visit_with(&mut collector);
}
term.visit_with(&mut collector);
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index c27c176e3..54da32770 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -103,7 +103,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
self.enforce_const_invariance(generics, variances);
// Functions are permitted to have unused generic parameters: make those invariant.
- if let ty::FnDef(..) = tcx.type_of(def_id).subst_identity().kind() {
+ if let ty::FnDef(..) = tcx.type_of(def_id).instantiate_identity().kind() {
for variance in variances.iter_mut() {
if *variance == ty::Bivariant {
*variance = ty::Invariant;
diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index 3b286bb9c..1a8ec5f08 100644
--- a/compiler/rustc_hir_analysis/src/variance/terms.rs
+++ b/compiler/rustc_hir_analysis/src/variance/terms.rs
@@ -12,7 +12,7 @@
use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use std::fmt;
use self::VarianceTerm::*;
@@ -32,8 +32,8 @@ pub enum VarianceTerm<'a> {
impl<'a> fmt::Debug for VarianceTerm<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ConstantTerm(c1) => write!(f, "{:?}", c1),
- TransformTerm(v1, v2) => write!(f, "({:?} \u{00D7} {:?})", v1, v2),
+ ConstantTerm(c1) => write!(f, "{c1:?}"),
+ TransformTerm(v1, v2) => write!(f, "({v1:?} \u{00D7} {v2:?})"),
InferredTerm(id) => write!(f, "[{}]", {
let InferredIndex(i) = id;
i
@@ -97,6 +97,11 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
}
}
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+ {
+ terms_cx.add_inferreds_for_item(def_id)
+ }
_ => {}
}
}