Skip to content

Rollup of 5 pull requests #119918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
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
3 changes: 3 additions & 0 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
@@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
.impl = inherent impls cannot have `~const` trait bounds
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
.trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
.inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
.object = trait objects cannot have `~const` trait bounds
.item = this item cannot have `~const` trait bounds
38 changes: 33 additions & 5 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -37,12 +37,17 @@ enum SelfSemantic {
}

/// What is the context that prevents using `~const`?
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
// almost identical. This gets rid of an abstraction layer which might be considered bad.
enum DisallowTildeConstContext<'a> {
TraitObject,
Fn(FnKind<'a>),
Trait(Span),
TraitImpl(Span),
Impl(Span),
TraitAssocTy(Span),
TraitImplAssocTy(Span),
InherentAssocTy(Span),
Item,
}

@@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> {
constness: Const::No,
polarity: ImplPolarity::Positive,
trait_ref,
..
} = parent
{
Some(trait_ref.path.span.shrink_to_lo())
@@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// suggestion for moving such bounds to the assoc const fns if available.
errors::TildeConstReason::Impl { span }
}
&DisallowTildeConstContext::TraitAssocTy(span) => {
errors::TildeConstReason::TraitAssocTy { span }
}
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
errors::TildeConstReason::TraitImplAssocTy { span }
}
&DisallowTildeConstContext::InherentAssocTy(span) => {
errors::TildeConstReason::InherentAssocTy { span }
}
DisallowTildeConstContext::TraitObject => {
errors::TildeConstReason::TraitObject
}
@@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_item_named(item.ident, "const");
}

let parent_is_const =
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();

match &item.kind {
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
if self
.outer_trait_or_trait_impl
.as_ref()
.and_then(TraitOrTraitImpl::constness)
.is_some()
if parent_is_const
|| ctxt == AssocCtxt::Trait
|| matches!(sig.header.constness, Const::Yes(_)) =>
{
@@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
self.visit_fn(kind, item.span, item.id);
}
AssocItemKind::Type(_) => {
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
Some(TraitOrTraitImpl::Trait { .. }) => {
DisallowTildeConstContext::TraitAssocTy(item.span)
}
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
DisallowTildeConstContext::TraitImplAssocTy(item.span)
}
None => DisallowTildeConstContext::InherentAssocTy(item.span),
});
self.with_tilde_const(disallowed, |this| {
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
})
}
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
}
}
17 changes: 17 additions & 0 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject {
pub span: Span,
}

// FIXME(effects): Consider making the note/reason the message of the diagnostic.
// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
#[derive(Diagnostic)]
#[diag(ast_passes_tilde_const_disallowed)]
pub struct TildeConstDisallowed {
@@ -598,6 +600,21 @@ pub enum TildeConstReason {
#[primary_span]
span: Span,
},
#[note(ast_passes_trait_assoc_ty)]
TraitAssocTy {
#[primary_span]
span: Span,
},
#[note(ast_passes_trait_impl_assoc_ty)]
TraitImplAssocTy {
#[primary_span]
span: Span,
},
#[note(ast_passes_inherent_assoc_ty)]
InherentAssocTy {
#[primary_span]
span: Span,
},
#[note(ast_passes_object)]
TraitObject,
#[note(ast_passes_item)]
8 changes: 6 additions & 2 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
@@ -2659,7 +2659,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
{
infer_replacements.push((a.span, suggested_ty.to_string()));
return suggested_ty;
return Ty::new_error_with_message(
self.tcx(),
a.span,
suggested_ty.to_string(),
);
}
}

@@ -2677,7 +2681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
{
infer_replacements.push((output.span, suggested_ty.to_string()));
suggested_ty
Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string())
} else {
visitor.visit_ty(output);
self.ast_ty_to_ty(output)
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ impl<'tcx> InferCtxt<'tcx> {
selection_cache: self.selection_cache.clone(),
evaluation_cache: self.evaluation_cache.clone(),
reported_trait_errors: self.reported_trait_errors.clone(),
reported_closure_mismatch: self.reported_closure_mismatch.clone(),
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
tainted_by_errors: self.tainted_by_errors.clone(),
err_count_on_creation: self.err_count_on_creation,
universe: self.universe.clone(),
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -278,7 +278,7 @@ pub struct InferCtxt<'tcx> {
/// avoid reporting the same error twice.
pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,

pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,

/// When an error occurs, we want to avoid reporting "derived"
/// errors that are due to this original failure. Normally, we
@@ -702,7 +702,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
selection_cache: Default::default(),
evaluation_cache: Default::default(),
reported_trait_errors: Default::default(),
reported_closure_mismatch: Default::default(),
reported_signature_mismatch: Default::default(),
tainted_by_errors: Cell::new(None),
err_count_on_creation: tcx.dcx().err_count(),
universe: Cell::new(ty::UniverseIndex::ROOT),
3 changes: 0 additions & 3 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -611,9 +611,6 @@ pub enum SelectionError<'tcx> {
NotConstEvaluatable(NotConstEvaluatable),
/// Exceeded the recursion depth during type projection.
Overflow(OverflowError),
/// Signaling that an error has already been emitted, to avoid
/// multiple errors being shown.
ErrorReporting,
/// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
/// We can thus not know whether the hidden type implements an auto trait, so
/// we should not presume anything about it.
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
@@ -302,7 +302,6 @@ impl EvaluationResult {
pub enum OverflowError {
Error(ErrorGuaranteed),
Canonical,
ErrorReporting,
}

impl From<ErrorGuaranteed> for OverflowError {
@@ -318,7 +317,6 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
match overflow_error {
OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
OverflowError::ErrorReporting => SelectionError::ErrorReporting,
}
}
}
Original file line number Diff line number Diff line change
@@ -947,9 +947,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
Overflow(_) => {
bug!("overflow should be handled before the `report_selection_error` path");
}
SelectionError::ErrorReporting => {
bug!("ErrorReporting Overflow should not reach `report_selection_err` call")
}
};

self.note_obligation_cause(&mut err, &obligation);
@@ -3459,14 +3456,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));

if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
// We check closures twice, with obligations flowing in different directions,
// but we want to complain about them only once.
return None;
}

self.reported_closure_mismatch.borrow_mut().insert((span, found_span));

let mut not_tupled = false;

let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
Original file line number Diff line number Diff line change
@@ -116,11 +116,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
r,
)
}
OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
})
}
Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
}
}
8 changes: 3 additions & 5 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -14,9 +14,9 @@ use super::util;
use super::util::closure_trait_ref_and_return_type;
use super::wf;
use super::{
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
Selection, SelectionError, SelectionResult, TraitQueryMode,
ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause,
ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection,
SelectionError, SelectionResult, TraitQueryMode,
};

use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -496,7 +496,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
Ok(_) => Ok(None),
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
})
.flat_map(Result::transpose)
@@ -1233,7 +1232,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(Some(c)) => self.evaluate_candidate(stack, &c),
Ok(None) => Ok(EvaluatedToAmbig),
Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
Err(..) => Ok(EvaluatedToErr),
}
}
6 changes: 3 additions & 3 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
@@ -1605,9 +1605,9 @@ mod prim_ref {}
/// type in the function pointer to the type at the function declaration, and the return value is
/// [`transmute`d][mem::transmute] from the type in the declaration to the type in the
/// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the
/// function expects a `NonNullI32` and the function pointer uses the ABI-compatible type
/// `Option<NonNullI32>`, and the value used for the argument is `None`, then this call is Undefined
/// Behavior since transmuting `None::<NonNullI32>` to `NonNullI32` violates the non-null
/// function expects a `NonZeroI32` and the function pointer uses the ABI-compatible type
/// `Option<NonZeroI32>`, and the value used for the argument is `None`, then this call is Undefined
/// Behavior since transmuting `None::<NonZeroI32>` to `NonZeroI32` violates the non-zero
/// requirement.
///
/// #### Requirements concerning target features
1 change: 0 additions & 1 deletion src/librustdoc/clean/blanket_impl.rs
Original file line number Diff line number Diff line change
@@ -81,7 +81,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
match infcx.evaluate_obligation(&obligation) {
Ok(eval_result) if eval_result.may_apply() => {}
Err(traits::OverflowError::Canonical) => {}
Err(traits::OverflowError::ErrorReporting) => {}
_ => continue 'blanket_impls,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-0.rs:21:6
|
LL | <T as /* FIXME: ~const */ Trait>::Assoc::func()
| ^ the trait `Trait` is not implemented for `T`
|
help: consider further restricting this bound
|
LL | const fn qualified<T: ~const Trait + Trait>() -> i32 {
| +++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// FIXME(effects): Collapse the revisions into one once we support `<Ty as ~const Trait>::Proj`.
// revisions: unqualified qualified
//[unqualified] check-pass
//[qualified] known-bug: unknown

#![feature(const_trait_impl, effects)]

#[const_trait]
trait Trait {
type Assoc: ~const Trait;
fn func() -> i32;
}

#[cfg(unqualified)]
const fn unqualified<T: ~const Trait>() -> i32 {
T::Assoc::func()
}

#[cfg(qualified)]
const fn qualified<T: ~const Trait>() -> i32 {
<T as /* FIXME: ~const */ Trait>::Assoc::func()
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-1.rs:23:43
|
LL | fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
| ^ the trait `Trait` is not implemented for `T`
|
help: consider further restricting this bound
|
LL | fn qualified<T: const Trait + Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
| +++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// FIXME(effects): Collapse the revisions into one once we support `<Ty as const Trait>::Proj`.
// revisions: unqualified qualified
//[unqualified] check-pass
//[qualified] known-bug: unknown

#![feature(const_trait_impl, effects, generic_const_exprs)]
#![allow(incomplete_features)]

#[const_trait]
trait Trait {
type Assoc: ~const Trait;
fn func() -> i32;
}

struct Type<const N: i32>;

#[cfg(unqualified)]
fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
Type
}

#[cfg(qualified)]
fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
Type
}

fn main() {}

This file was deleted.

This file was deleted.

28 changes: 21 additions & 7 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
// known-bug: #110395
// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again.
#![feature(const_trait_impl, effects)]

#![feature(const_trait_impl)]
#[const_trait]
trait Add<Rhs = Self> {
type Output;

fn add(self, other: Rhs) -> Self::Output;
}

impl const Add for i32 {
type Output = Self;

fn add(self, other: Self) -> Self::Output {
self + other
}
}

struct NonConstAdd(i32);

impl std::ops::Add for NonConstAdd {
impl Add for NonConstAdd {
type Output = Self;

fn add(self, rhs: Self) -> Self {
NonConstAdd(self.0 + rhs.0)
NonConstAdd(self.0.add(rhs.0))
}
}

#[const_trait]
trait Foo {
type Bar: ~const std::ops::Add;
type Bar: ~const Add;
}

impl const Foo for NonConstAdd {
type Bar = NonConstAdd;
type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
}

#[const_trait]
trait Baz {
type Qux: std::ops::Add;
type Qux: Add;
}

impl const Baz for NonConstAdd {
22 changes: 11 additions & 11 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: `~const` is not allowed here
--> $DIR/assoc-type.rs:17:15
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
--> $DIR/assoc-type.rs:35:16
|
LL | type Bar: ~const std::ops::Add;
| ^^^^^^
LL | type Bar = NonConstAdd;
| ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd`
|
= note: this item cannot have `~const` trait bounds

error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/assoc-type.rs:17:22
= help: the trait `Add` is implemented for `NonConstAdd`
note: required by a bound in `Foo::Bar`
--> $DIR/assoc-type.rs:31:15
|
LL | type Bar: ~const std::ops::Add;
| ^^^^^^^^^^^^^
LL | type Bar: ~const Add;
| ^^^^^^^^^^ required by this bound in `Foo::Bar`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -72,15 +72,23 @@ error: `~const` is not allowed here
LL | type Type<T: ~const Trait>: ~const Trait;
| ^^^^^^
|
= note: this item cannot have `~const` trait bounds
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
--> $DIR/tilde-const-invalid-places.rs:25:5
|
LL | type Type<T: ~const Trait>: ~const Trait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:25:33
|
LL | type Type<T: ~const Trait>: ~const Trait;
| ^^^^^^
|
= note: this item cannot have `~const` trait bounds
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
--> $DIR/tilde-const-invalid-places.rs:25:5
|
LL | type Type<T: ~const Trait>: ~const Trait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:28:30
@@ -108,7 +116,11 @@ error: `~const` is not allowed here
LL | type Type<T: ~const Trait> = ();
| ^^^^^^
|
= note: this item cannot have `~const` trait bounds
note: associated types in non-const impls cannot have `~const` trait bounds
--> $DIR/tilde-const-invalid-places.rs:34:5
|
LL | type Type<T: ~const Trait> = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:36:30
@@ -136,7 +148,11 @@ error: `~const` is not allowed here
LL | type Type<T: ~const Trait> = ();
| ^^^^^^
|
= note: this item cannot have `~const` trait bounds
note: inherent associated types cannot have `~const` trait bounds
--> $DIR/tilde-const-invalid-places.rs:44:5
|
LL | type Type<T: ~const Trait> = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:46:30
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// check-pass
#![feature(const_trait_impl, effects)]

#[const_trait]
trait Trait {
// FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds)
// don't look super useful. Should we forbid them again?
type Assoc<T: ~const Bound>;
}

impl const Trait for () {
type Assoc<T: ~const Bound> = T;
}

#[const_trait]
trait Bound {}

fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/traits/method-argument-mismatch-variance-ice-119867.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait Deserialize {
fn deserialize(&self);
}

struct ArchivedVec<T>(T);

impl<T> Deserialize for ArchivedVec<T> {
fn deserialize(s: _) {}
//~^ ERROR: `_` is not allowed within types on item signatures
//~| ERROR: has a `&self` declaration in the trait, but not in the impl
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/method-argument-mismatch-variance-ice-119867.rs:8:23
|
LL | fn deserialize(s: _) {}
| ^ not allowed in type signatures
|
help: try replacing `_` with the type in the corresponding trait method signature
|
LL | fn deserialize(s: &ArchivedVec<T>) {}
| ~~~~~~~~~~~~~~~

error[E0186]: method `deserialize` has a `&self` declaration in the trait, but not in the impl
--> $DIR/method-argument-mismatch-variance-ice-119867.rs:8:5
|
LL | fn deserialize(&self);
| ---------------------- `&self` used in trait
...
LL | fn deserialize(s: _) {}
| ^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0121, E0186.
For more information about an error, try `rustc --explain E0121`.