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
6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,11 @@ pub(super) fn check_const_item<'tcx>(
if tcx.is_direct_const(def_id.into()) {
if !tcx.features().const_param_ty_unchecked() {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
ObligationCause::new(
tcx.ty_span(def_id),
def_id,
ObligationCauseCode::ConstItemTy(item_ty),
),
wfcx.param_env,
item_ty,
tcx.require_lang_item(LangItem::ConstParamTy, span),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ pub enum ObligationCauseCode<'tcx> {
/// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
ConstParam(Ty<'tcx>),

/// Requirement for the type of a const item used in the type system to implement
/// `ConstParamTy`.
ConstItemTy(Ty<'tcx>),
Comment thread
YUZHEthefool marked this conversation as resolved.

/// Obligations emitted during the normalization of a free type alias.
TypeAlias(ObligationCauseCodeHandle<'tcx>, Span, DefId),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.emit_err();
}

// Report a const-param specific error
if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
{
return self.report_const_param_not_wf(ty, &obligation).emit_err();
// Report a `ConstParamTy`-specific error
match *obligation.cause.code().peel_derives() {
ObligationCauseCode::ConstParam(ty) => {
return self
.report_const_param_ty_error(
ty,
self.tcx.ty_span(obligation.cause.body_def_id),
&obligation,
)
.emit_err();
}
ObligationCauseCode::ConstItemTy(ty) => {
return self
.report_const_param_ty_error(ty, obligation.cause.span, &obligation)
.emit_err();
}
_ => {}
}

let bound_predicate = obligation.predicate.kind();
Expand Down Expand Up @@ -1421,14 +1434,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
true
}

fn report_const_param_not_wf(
fn report_const_param_ty_error(
&self,
ty: Ty<'tcx>,
span: Span,
obligation: &PredicateObligation<'tcx>,
) -> Diag<'a> {
let def_id = obligation.cause.body_def_id;
let span = self.tcx.ty_span(def_id);

let mut file = None;
let ty_str = self.tcx.short_string(ty, &mut file);
let mut diag = match ty.kind() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3917,6 +3917,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
| ObligationCauseCode::AlwaysApplicableImpl
| ObligationCauseCode::ConstParam(_)
| ObligationCauseCode::ConstItemTy(_)
| ObligationCauseCode::ReferenceOutlivesReferent(..)
| ObligationCauseCode::ObjectTypeBound(..) => {}
ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. } => {
Expand Down
44 changes: 43 additions & 1 deletion compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ pub fn clause_obligations<'tcx>(
wf.add_wf_preds_for_term(ty.into());
}
ty::ClauseKind::Projection(t) => {
if !t.projection_term.kind.is_type() {
assert!(matches!(
t.projection_term.kind,
ty::AliasTermKind::ProjectionConst { .. }
));
wf.require_const_item_ty(t.projection_term.expect_ct());
}
wf.add_wf_preds_for_projection_term(t.projection_term);
wf.add_wf_preds_for_term(t.term);
}
Expand Down Expand Up @@ -570,6 +577,33 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
}

fn require_const_item_ty(&mut self, ct: ty::AliasConst<'tcx>) {
let ty = ct.type_of(self.tcx()).skip_norm_wip();

if ct.kind.is_direct_const(self.tcx()) {
Comment thread
YUZHEthefool marked this conversation as resolved.
// This is already checked in `wfcheck::check_const_item`.
return;
}

if self.tcx().features().const_param_ty_unchecked() || ty.has_escaping_bound_vars() {
return;
}

Comment thread
BoxyUwU marked this conversation as resolved.
let cause = self.cause(ObligationCauseCode::ConstItemTy(ty));
let trait_ref = ty::TraitRef::new(
self.tcx(),
self.tcx().require_lang_item(LangItem::ConstParamTy, cause.span),
[ty],
);
self.out.push(traits::Obligation::with_depth(
self.tcx(),
cause,
self.recursion_depth,
self.param_env,
ty::Binder::dummy(trait_ref),
));
}

/// Pushes all the predicates needed to validate that `term` is WF into `out`.
#[instrument(level = "debug", skip(self))]
fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) {
Expand Down Expand Up @@ -1026,8 +1060,16 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {

if !t.has_escaping_bound_vars() {
for projection in data.projection_bounds() {
let projection = projection.with_self_ty(tcx, t);
let projection_pred = projection.skip_binder();
if matches!(
projection_pred.projection_term.kind,
ty::AliasTermKind::ProjectionConst { .. }
) {
self.require_const_item_ty(projection_pred.projection_term.expect_ct());
}

let pred_binder = projection
.with_self_ty(tcx, t)
.map_bound(|p| {
p.term.as_const().map(|ct| {
let assoc_const_ty = tcx
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items, gca_min_const_items)]
#![allow(incomplete_features)]

trait Trait {
const F: fn();
}

trait Nested {
type Out: Trait<F = { || {} }>;
//~^ ERROR using function pointers as const generic parameters is forbidden
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0741]: using function pointers as const generic parameters is forbidden
--> $DIR/associated-type-bound-issue-161100.rs:11:21
|
LL | type Out: Trait<F = { || {} }>;
| ^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items, gca_min_const_items)]

struct S;
const C: S = S;

trait Trait {
const F: S;
}

fn take(_: impl Trait<F = { core::gca!(C) }>) {}
//~^ ERROR `S` must implement `ConstParamTy`

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/direct-const-item-associated-equality-issue-161100.rs:12:23
|
LL | fn take(_: impl Trait<F = { core::gca!(C) }>) {}
| ^^^^^^^^^^^^^^^^^^^^^
|
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
LL + #[derive(ConstParamTy, PartialEq, Eq)]
LL | struct S;
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items, gca_min_const_items)]

trait Trait {
const F: fn();
}

fn take(_: &dyn Trait<F = { || {} }>) {}
//~^ ERROR using function pointers as const generic parameters is forbidden

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0741]: using function pointers as const generic parameters is forbidden
--> $DIR/dyn-associated-const-issue-161100.rs:9:13
|
LL | fn take(_: &dyn Trait<F = { || {} }>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items)]
#![feature(gca_min_const_items)]

trait Trait {
const F: fn();
}

fn take(_: impl Trait<F = { || {} }>) {}
//~^ ERROR using function pointers as const generic parameters is forbidden

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0741]: using function pointers as const generic parameters is forbidden
--> $DIR/fn-ptr-const-param-issue-161100.rs:10:23
|
LL | fn take(_: impl Trait<F = { || {} }>) {}
| ^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items)]
#![feature(gca_min_const_items)]

enum Foo {
Unit,
Function(fn()),
}

trait Trait {
const X: Foo;
}

fn unit(_: impl Trait<X = { Foo::Unit }>) {}
//~^ ERROR `Foo` must implement `ConstParamTy`

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/non-const-param-ty-associated-const-equality-issue-161100.rs:15:23
|
LL | fn unit(_: impl Trait<X = { Foo::Unit }>) {}
| ^^^^^^^^^^^^^^^^^
|
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the enum
|
LL + #[derive(ConstParamTy, PartialEq, Eq)]
LL | enum Foo {
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//@ compile-flags: -Znext-solver=globally

#![feature(gca_const_items, gca_min_const_items)]

trait Trait {
const F: fn();
}

fn take<T>() where T: Trait<F = { || {} }> {}
//~^ ERROR using function pointers as const generic parameters is forbidden

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0741]: using function pointers as const generic parameters is forbidden
--> $DIR/where-clause-issue-161100.rs:9:29
|
LL | fn take<T>() where T: Trait<F = { || {} }> {}
| ^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0741`.
Loading