Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3031,7 +3031,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
if tcx.is_type_const(def_id) {
// FIXME(gca): Intentionally disallowing paths to inherent associated non-type constants
// until a refactoring for how generic args for IACs are represented has been landed.
let is_inherent_assoc_const = tcx.def_kind(def_id)
== DefKind::AssocConst { is_type_const: false }
&& tcx.def_kind(tcx.parent(def_id)) == DefKind::Impl { of_trait: false };
if tcx.is_type_const(def_id)
|| tcx.features().generic_const_args() && !is_inherent_assoc_const
{
Ok(())
} else {
let mut err = self.dcx().struct_span_err(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_infer/src/infer/relate/generalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl<'tcx> InferCtxt<'tcx> {
bug!("generalized `{source_term:?} to infer, not an alias");
};
match source_alias.kind(self.tcx) {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst { .. } => {
// FIXME: This does not handle subtyping correctly, we could
// instead create a new inference variable `?normalized_source`, emitting
// `Projection(normalized_source, ?ty_normalized)` and
Expand All @@ -204,8 +204,8 @@ impl<'tcx> InferCtxt<'tcx> {
| ty::AliasTermKind::OpaqueTy => {
return Err(TypeError::CyclicTy(source_term.expect_type()));
}
ty::AliasTermKind::InherentConst
| ty::AliasTermKind::FreeConst
ty::AliasTermKind::InherentConst { .. }
| ty::AliasTermKind::FreeConst { .. }
| ty::AliasTermKind::UnevaluatedConst => {
return Err(TypeError::CyclicConst(source_term.expect_const()));
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,17 +212,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
ty::AliasTermKind::ProjectionTy
}
}
DefKind::AssocConst { .. } => {
DefKind::AssocConst { is_type_const } => {
if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
{
ty::AliasTermKind::InherentConst
ty::AliasTermKind::InherentConst { is_type_const }
} else {
ty::AliasTermKind::ProjectionConst
ty::AliasTermKind::ProjectionConst { is_type_const }
}
}
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
DefKind::TyAlias => ty::AliasTermKind::FreeTy,
DefKind::Const { .. } => ty::AliasTermKind::FreeConst,
DefKind::Const { is_type_const } => ty::AliasTermKind::FreeConst { is_type_const },
DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => {
ty::AliasTermKind::UnevaluatedConst
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3152,7 +3152,7 @@ define_print! {

ty::AliasTerm<'tcx> {
match self.kind(p.tcx()) {
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => p.pretty_print_inherent_projection(*self)?,
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst { .. } => p.pretty_print_inherent_projection(*self)?,
ty::AliasTermKind::ProjectionTy => {
if !(p.should_print_verbose() || with_reduced_queries())
&& p.tcx().is_impl_trait_in_trait(self.def_id)
Expand All @@ -3163,10 +3163,10 @@ define_print! {
}
}
ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::FreeConst { .. }
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
| ty::AliasTermKind::ProjectionConst { .. } => {
p.print_def_path(self.def_id, self.args)?;
}
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,11 +948,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
ty::AliasTermKind::InherentTy
| ty::AliasTermKind::InherentConst
| ty::AliasTermKind::InherentConst { .. }
| ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::FreeConst { .. }
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => None,
| ty::AliasTermKind::ProjectionConst { .. } => None,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,8 @@ where
&mut self,
goal: Goal<I, ty::NormalizesTo<I>>,
) -> QueryResult<I> {
if let Some(normalized_const) = self.evaluate_const(
goal.param_env,
ty::UnevaluatedConst::new(
goal.predicate.alias.def_id.try_into().unwrap(),
goal.predicate.alias.args,
),
) {
let uv = goal.predicate.alias.expect_ct(self.cx());
if let Some(normalized_const) = self.evaluate_const(goal.param_env, uv) {
self.instantiate_normalizes_to_term(goal, normalized_const.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,24 @@ where
.map(|pred| goal.with(cx, pred)),
);

let actual = if free_alias.kind(cx).is_type() {
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args).into()
} else {
cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args).into()
let actual = match free_alias.kind(cx) {
ty::AliasTermKind::FreeTy => {
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args).into()
}
ty::AliasTermKind::FreeConst { is_type_const: true } => {
cx.const_of_item(free_alias.def_id).instantiate(cx, free_alias.args).into()
}
ty::AliasTermKind::FreeConst { is_type_const: false } => {
if let Some(normalized_const) =
self.evaluate_const(goal.param_env, free_alias.expect_ct(cx))
{
normalized_const.into()
} else {
return self
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
}
}
kind => panic!("expected free alias, found {kind:?}"),
};

self.instantiate_normalizes_to_term(goal, actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,23 @@ where
.map(|pred| goal.with(cx, pred)),
);

let normalized = if inherent.kind(cx).is_type() {
cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into()
} else {
cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).into()
let normalized = match inherent.kind(cx) {
ty::AliasTermKind::InherentTy => {
cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into()
}
ty::AliasTermKind::InherentConst { is_type_const: true } => {
cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).into()
}
ty::AliasTermKind::InherentConst { is_type_const: false } => {
// FIXME(gca): This is dead code at the moment. It should eventually call
// self.evaluate_const like projected consts do in consider_impl_candidate in
// normalizes_to/mod.rs. However, how generic args are represented for IACs is up in
// the air right now.
// Will self.evaluate_const eventually take the inherent_args or the impl_args form
// of args? It might be either.
panic!("References to inherent associated consts should have been blocked");
}
kind => panic!("expected inherent alias, found {kind:?}"),
};
self.instantiate_normalizes_to_term(goal, normalized);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
Expand Down
29 changes: 21 additions & 8 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ where
debug_assert!(self.term_is_fully_unconstrained(goal));
let cx = self.cx();
match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst { .. } => {
let trait_ref = goal.predicate.alias.trait_ref(cx);
let (_, proven_via) =
self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
Expand Down Expand Up @@ -83,11 +83,11 @@ where
},
)
}
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => {
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst { .. } => {
self.normalize_inherent_associated_term(goal)
}
ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst => {
ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst { .. } => {
self.normalize_free_alias(goal)
}
ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal),
Expand Down Expand Up @@ -264,7 +264,7 @@ where
let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| {
let error_term = match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(),
ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(),
ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(),
kind => panic!("expected projection, found {kind:?}"),
};
ecx.instantiate_normalizes_to_term(goal, error_term);
Expand Down Expand Up @@ -380,15 +380,28 @@ where
// Finally we construct the actual value of the associated type.
let term = match goal.predicate.alias.kind(cx) {
ty::AliasTermKind::ProjectionTy => {
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
cx.type_of(target_item_def_id).instantiate(cx, target_args).into()
}
ty::AliasTermKind::ProjectionConst => {
cx.const_of_item(target_item_def_id).map_bound(|ct| ct.into())
ty::AliasTermKind::ProjectionConst { is_type_const: true } => {
cx.const_of_item(target_item_def_id).instantiate(cx, target_args).into()
}
ty::AliasTermKind::ProjectionConst { is_type_const: false } => {
let uv = ty::UnevaluatedConst::new(
target_item_def_id.try_into().unwrap(),
target_args,
);
if let Some(eval) = ecx.evaluate_const(goal.param_env, uv) {
eval.into()
} else {
return ecx.evaluate_added_goals_and_make_canonical_response(
Certainty::AMBIGUOUS,
);
}
}
kind => panic!("expected projection, found {kind:?}"),
};

ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args));
ecx.instantiate_normalizes_to_term(goal, term);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
};

if let Some(lhs) = lhs.to_alias_term()
&& let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = lhs.kind(self.tcx)
&& let ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::ProjectionConst { .. } = lhs.kind(self.tcx)
&& let Some((better_type_err, expected_term)) =
derive_better_type_error(lhs, rhs)
{
Expand All @@ -1597,7 +1598,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
better_type_err,
)
} else if let Some(rhs) = rhs.to_alias_term()
&& let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = rhs.kind(self.tcx)
&& let ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::ProjectionConst { .. } = rhs.kind(self.tcx)
&& let Some((better_type_err, expected_term)) =
derive_better_type_error(rhs, lhs)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,8 @@ impl<'tcx> BestObligation<'tcx> {
self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
}
Some(ty::PredicateKind::NormalizesTo(pred))
if let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst =
pred.alias.kind(tcx) =>
if let ty::AliasTermKind::ProjectionTy
| ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind(tcx) =>
{
self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?;
self.detect_non_well_formed_assoc_item(goal, pred.alias)?;
Expand Down Expand Up @@ -450,7 +450,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
ty::PredicateKind::NormalizesTo(normalizes_to)
if matches!(
normalizes_to.alias.kind(tcx),
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst { .. }
) =>
{
ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate {
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_trait_selection/src/traits/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,24 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
),
);
self.depth += 1;
let res = if free.kind(infcx.tcx).is_type() {
infcx.tcx.type_of(free.def_id).instantiate(infcx.tcx, free.args).fold_with(self).into()
} else {
infcx
let res = match free.kind(infcx.tcx) {
ty::AliasTermKind::FreeTy => infcx
.tcx
.type_of(free.def_id)
.instantiate(infcx.tcx, free.args)
.fold_with(self)
.into(),
ty::AliasTermKind::FreeConst { is_type_const: true } => infcx
.tcx
.const_of_item(free.def_id)
.instantiate(infcx.tcx, free.args)
.fold_with(self)
.into()
.into(),
ty::AliasTermKind::FreeConst { is_type_const: false } => {
super::evaluate_const(infcx, free.to_term(infcx.tcx).expect_const(), self.param_env)
.into()
}
kind => panic!("expected free alias, found {kind:?}"),
};
self.depth -= 1;
res
Expand Down
52 changes: 38 additions & 14 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,12 @@ fn normalize_to_error<'a, 'tcx>(
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::FreeTy => selcx.infcx.next_ty_var(cause.span).into(),
ty::AliasTermKind::FreeConst
| ty::AliasTermKind::InherentConst
ty::AliasTermKind::FreeConst { .. }
| ty::AliasTermKind::InherentConst { .. }
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => selcx.infcx.next_const_var(cause.span).into(),
| ty::AliasTermKind::ProjectionConst { .. } => {
selcx.infcx.next_const_var(cause.span).into()
}
};
let mut obligations = PredicateObligations::new();
obligations.push(Obligation {
Expand Down Expand Up @@ -543,10 +545,22 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
));
}

let term: Term<'tcx> = if alias_term.kind(tcx).is_type() {
tcx.type_of(alias_term.def_id).instantiate(tcx, args).into()
} else {
tcx.const_of_item(alias_term.def_id).instantiate(tcx, args).into()
let term: Term<'tcx> = match alias_term.kind(tcx) {
ty::AliasTermKind::InherentTy => {
tcx.type_of(alias_term.def_id).instantiate(tcx, args).into()
}
ty::AliasTermKind::InherentConst { is_type_const: true } => {
tcx.const_of_item(alias_term.def_id).instantiate(tcx, args).into()
}
ty::AliasTermKind::InherentConst { is_type_const: false } => {
// FIXME(gca): This is dead code at the moment. It should eventually call
// super::evaluate_const like projected consts do in confirm_impl_candidate in this
// file. However, how generic args are represented for IACs is up in the air right now.
// Will super::evaluate_const eventually take the inherent_args or the impl_args form of
// args? It might be either.
panic!("References to inherent associated consts should have been blocked");
}
kind => panic!("expected inherent alias, found {kind:?}"),
};

let mut term = selcx.infcx.resolve_vars_if_possible(term);
Expand Down Expand Up @@ -2044,12 +2058,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_term.defining_node);

let term = if obligation.predicate.kind(tcx).is_type() {
tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into())
} else {
tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into())
};

let progress = if !tcx.check_args_compatible(assoc_term.item.def_id, args) {
let msg = "impl item and trait item have different parameters";
let span = obligation.cause.span;
Expand All @@ -2061,7 +2069,23 @@ fn confirm_impl_candidate<'cx, 'tcx>(
Progress { term: err, obligations: nested }
} else {
assoc_term_own_obligations(selcx, obligation, &mut nested);
Progress { term: term.instantiate(tcx, args), obligations: nested }

let term = match obligation.predicate.kind(tcx) {
ty::AliasTermKind::ProjectionTy => {
tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args).into()
}
ty::AliasTermKind::ProjectionConst { is_type_const: true } => {
tcx.const_of_item(assoc_term.item.def_id).instantiate(tcx, args).into()
}
ty::AliasTermKind::ProjectionConst { is_type_const: false } => {
let uv = ty::UnevaluatedConst::new(assoc_term.item.def_id, args);
let ct = ty::Const::new_unevaluated(tcx, uv);
super::evaluate_const(selcx.infcx, ct, param_env).into()
}
kind => panic!("expected projection alias, found {kind:?}"),
};

Progress { term, obligations: nested }
};
Ok(Projected::Progress(progress))
}
Expand Down
Loading
Loading