Skip to content
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

Rollup of 5 pull requests #119918

Closed
wants to merge 10 commits into from
3 changes: 3 additions & 0 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 33 additions & 5 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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(_)) =>
{
Expand All @@ -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)),
}
}
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)]
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
);
}
}

Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ impl EvaluationResult {
pub enum OverflowError {
Error(ErrorGuaranteed),
Canonical,
ErrorReporting,
}

impl From<ErrorGuaranteed> for OverflowError {
Expand All @@ -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
Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
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
Expand Up @@ -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};
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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),
}
}
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/clean/blanket_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
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.

Loading
Loading