Auto merge of #122713 - matthiaskrgr:rollup-81grkpm, r=matthiaskrgr

Rollup of 11 pull requests

Successful merges:

 - #121258 (Reject overly generic assoc const binding types)
 - #121823 (never patterns: suggest `!` patterns on non-exhaustive matches)
 - #122060 (Stabilize `imported_main`)
 - #122158 (Provide structured suggestion for `#![feature(foo)]`)
 - #122642 (Improve wording of `Vec::swap_remove`)
 - #122675 (core: document default attribute stabilization)
 - #122687 (`NormalizesTo`: return nested goals to caller)
 - #122693 (Fix heading anchors in doc pages.)
 - #122699 (Fix a typo in the 1.77.0 relnotes)
 - #122700 (Remove redundant files, rename base riscv32 file)
 - #122701 (Detect allocator for box in `must_not_suspend` lint)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-18 21:27:04 +00:00
commit 3c85e56249
179 changed files with 2567 additions and 770 deletions

View File

@ -82,7 +82,7 @@ Cargo
- [Extend the build directive syntax with `cargo::`.](https://github.com/rust-lang/cargo/pull/12201/)
- [Stabilize metadata `id` format as `PackageIDSpec`.](https://github.com/rust-lang/cargo/pull/12914/)
- [Pull out as `cargo-util-schemas` as a crate.](https://github.com/rust-lang/cargo/pull/13178/)
- [Pull out `cargo-util-schemas` as a crate.](https://github.com/rust-lang/cargo/pull/13178/)
- [Strip all debuginfo when debuginfo is not requested.](https://github.com/rust-lang/cargo/pull/13257/)
- [Inherit jobserver from env for all kinds of runners.](https://github.com/rust-lang/cargo/pull/12776/)
- [Deprecate rustc plugin support in cargo.](https://github.com/rust-lang/cargo/pull/13248/)

View File

@ -99,7 +99,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
#[allow(rustc::untranslatable_diagnostic)]
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
let FnCallNonConst { caller, callee, args, span, call_source, feature } = *self;
let ConstCx { tcx, param_env, .. } = *ccx;
let ConstCx { tcx, param_env, body, .. } = *ccx;
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
let trait_ref = TraitRef::from_method(tcx, trait_id, args);
@ -297,10 +297,12 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
ccx.const_kind(),
));
if let Some(feature) = feature
&& ccx.tcx.sess.is_nightly_build()
{
err.help(format!("add `#![feature({feature})]` to the crate attributes to enable",));
if let Some(feature) = feature {
ccx.tcx.disabled_nightly_features(
&mut err,
body.source.def_id().as_local().map(|local| ccx.tcx.local_def_id_to_hir_id(local)),
[(String::new(), feature)],
);
}
if let ConstContext::Static(_) = ccx.const_kind() {

View File

@ -203,6 +203,8 @@ declare_features! (
(accepted, impl_header_lifetime_elision, "1.31.0", Some(15872)),
/// Allows referencing `Self` and projections in impl-trait.
(accepted, impl_trait_projections, "1.74.0", Some(103532)),
/// Allows using imported `main` function
(accepted, imported_main, "CURRENT_RUSTC_VERSION", Some(28937)),
/// Allows using `a..=b` and `..=b` as inclusive range syntaxes.
(accepted, inclusive_range_syntax, "1.26.0", Some(28237)),
/// Allows inferring outlives requirements (RFC 2093).

View File

@ -495,8 +495,6 @@ declare_features! (
(unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
(unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
/// Allows using imported `main` function
(unstable, imported_main, "1.53.0", Some(28937)),
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
/// Allow anonymous constants from an inline `const` block

View File

@ -118,6 +118,11 @@ hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
.label = overflowed on value after {$discr}
.note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding =
the type of the associated constant `{$assoc_const}` cannot capture late-bound generic parameters
.label = its type cannot capture the late-bound {$var_def_kind} `{$var_name}`
.var_defined_here_label = the late-bound {$var_def_kind} `{$var_name}` is defined here
hir_analysis_field_already_declared =
field `{$field_name}` is already declared
.label = field already declared
@ -316,6 +321,22 @@ hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot captur
.label = `impl Trait` implicitly captures all lifetimes in scope
.note = lifetime declared here
hir_analysis_param_in_ty_of_assoc_const_binding =
the type of the associated constant `{$assoc_const}` must not depend on {$param_category ->
[self] `Self`
[synthetic] `impl Trait`
*[normal] generic parameters
}
.label = its type must not depend on {$param_category ->
[self] `Self`
[synthetic] `impl Trait`
*[normal] the {$param_def_kind} `{$param_name}`
}
.param_defined_here_label = {$param_category ->
[synthetic] the `impl Trait` is specified here
*[normal] the {$param_def_kind} `{$param_name}` is defined here
}
hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
.help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
@ -432,6 +453,8 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
.label = needs at most one field with non-trivial size or alignment, but has {$field_count}
.labels = this field has non-zero size or requires alignment
hir_analysis_ty_of_assoc_const_binding_note = `{$assoc_const}` has type `{$ty}`
hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
.label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
.note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type

View File

@ -1,12 +1,15 @@
use rustc_data_structures::fx::FxIndexMap;
use std::ops::ControlFlow;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{codes::*, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::{self as ty, Ty};
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
use rustc_span::symbol::Ident;
use rustc_span::{ErrorGuaranteed, Span};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_trait_selection::traits;
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use smallvec::SmallVec;
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
@ -433,14 +436,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
binding.kind
{
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
// Since the arguments passed to the alias type above may contain early-bound
// generic parameters, the instantiated type may contain some as well.
// Therefore wrap it in `EarlyBinder`.
// FIXME(fmease): Reject escaping late-bound vars.
tcx.feed_anon_const_type(
anon_const.def_id,
ty::EarlyBinder::bind(ty.skip_binder()),
);
let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id);
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
}
alias_ty
@ -530,3 +527,167 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
Ok(())
}
}
/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
///
/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the
/// arrival of *generic const generics*[^1].
///
/// It might actually be possible that we can already support early-bound generic params
/// in such types if we just lifted some more checks in other places, too, for example
/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
/// probably gate this behind another feature flag.
///
/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
fn check_assoc_const_binding_type<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_const: Ident,
ty: ty::Binder<'tcx, Ty<'tcx>>,
hir_id: hir::HirId,
) -> Ty<'tcx> {
// We can't perform the checks for early-bound params during name resolution unlike E0770
// because this information depends on *type* resolution.
// We can't perform these checks in `resolve_bound_vars` either for the same reason.
// Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
// resolved type of `Trait::C` in order to know if it references `'a` or not.
let ty = ty.skip_binder();
if !ty.has_param() && !ty.has_escaping_bound_vars() {
return ty;
}
let mut collector = GenericParamAndBoundVarCollector {
tcx,
params: Default::default(),
vars: Default::default(),
depth: ty::INNERMOST,
};
let mut guar = ty.visit_with(&mut collector).break_value();
let ty_note = ty
.make_suggestable(tcx, false)
.map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
let enclosing_item_owner_id = tcx
.hir()
.parent_owner_iter(hir_id)
.find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
.unwrap();
let generics = tcx.generics_of(enclosing_item_owner_id);
for index in collector.params {
let param = generics.param_at(index as _, tcx);
let is_self_param = param.name == rustc_span::symbol::kw::SelfUpper;
guar.get_or_insert(tcx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
span: assoc_const.span,
assoc_const,
param_name: param.name,
param_def_kind: tcx.def_descr(param.def_id),
param_category: if is_self_param {
"self"
} else if param.kind.is_synthetic() {
"synthetic"
} else {
"normal"
},
param_defined_here_label:
(!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
ty_note,
}));
}
for (var_def_id, var_name) in collector.vars {
guar.get_or_insert(tcx.dcx().emit_err(
crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
span: assoc_const.span,
assoc_const,
var_name,
var_def_kind: tcx.def_descr(var_def_id),
var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
ty_note,
},
));
}
let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
Ty::new_error(tcx, guar)
}
struct GenericParamAndBoundVarCollector<'tcx> {
tcx: TyCtxt<'tcx>,
params: FxIndexSet<u32>,
vars: FxIndexSet<(DefId, Symbol)>,
depth: ty::DebruijnIndex,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'tcx> {
type Result = ControlFlow<ErrorGuaranteed>;
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
binder: &ty::Binder<'tcx, T>,
) -> Self::Result {
self.depth.shift_in(1);
let result = binder.super_visit_with(self);
self.depth.shift_out(1);
result
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
match ty.kind() {
ty::Param(param) => {
self.params.insert(param.index);
}
ty::Bound(db, bt) if *db >= self.depth => {
self.vars.insert(match bt.kind {
ty::BoundTyKind::Param(def_id, name) => (def_id, name),
ty::BoundTyKind::Anon => {
let reported = self
.tcx
.dcx()
.delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
return ControlFlow::Break(reported);
}
});
}
_ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
_ => {}
}
ControlFlow::Continue(())
}
fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
match re.kind() {
ty::ReEarlyParam(param) => {
self.params.insert(param.index);
}
ty::ReBound(db, br) if db >= self.depth => {
self.vars.insert(match br.kind {
ty::BrNamed(def_id, name) => (def_id, name),
ty::BrAnon | ty::BrEnv => {
let guar = self
.tcx
.dcx()
.delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
return ControlFlow::Break(guar);
}
});
}
_ => {}
}
ControlFlow::Continue(())
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
match ct.kind() {
ty::ConstKind::Param(param) => {
self.params.insert(param.index);
}
ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
let guar = self.tcx.dcx().delayed_bug("unexpected escaping late-bound const var");
return ControlFlow::Break(guar);
}
_ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
_ => {}
}
ControlFlow::Continue(())
}
}

View File

@ -16,7 +16,7 @@ use rustc_middle::ty::{
self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
};
use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
use rustc_span::symbol::kw;
use rustc_span::symbol::{kw, sym};
use smallvec::SmallVec;
/// Report an error that a generic argument did not match the generic parameter that was
@ -41,9 +41,11 @@ fn generic_arg_mismatch_err(
if let GenericParamDefKind::Const { .. } = param.kind {
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
err.help("const arguments cannot yet be inferred with `_`");
if sess.is_nightly_build() {
err.help("add `#![feature(generic_arg_infer)]` to the crate attributes to enable");
}
tcx.disabled_nightly_features(
&mut err,
param.def_id.as_local().map(|local| tcx.local_def_id_to_hir_id(local)),
[(String::new(), sym::generic_arg_infer)],
);
}
}

View File

@ -291,12 +291,16 @@ fn default_body_is_unstable(
reason: reason_str,
});
let inject_span = item_did
.as_local()
.and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id)));
rustc_session::parse::add_feature_diagnostics_for_issue(
&mut err,
&tcx.sess,
feature,
rustc_feature::GateIssue::Library(issue),
false,
inject_span,
);
err.emit();

View File

@ -999,9 +999,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
// Implments `ConstParamTy`, suggest adding the feature to enable.
Ok(..) => true,
};
if may_suggest_feature && tcx.sess.is_nightly_build() {
diag.help(
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
if may_suggest_feature {
tcx.disabled_nightly_features(
&mut diag,
Some(param.hir_id),
[(
" more complex and user defined types".to_string(),
sym::adt_const_params,
)],
);
}

View File

@ -295,6 +295,44 @@ pub struct AssocTypeBindingNotAllowed {
pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_param_in_ty_of_assoc_const_binding)]
pub(crate) struct ParamInTyOfAssocConstBinding<'tcx> {
#[primary_span]
#[label]
pub span: Span,
pub assoc_const: Ident,
pub param_name: Symbol,
pub param_def_kind: &'static str,
pub param_category: &'static str,
#[label(hir_analysis_param_defined_here_label)]
pub param_defined_here_label: Option<Span>,
#[subdiagnostic]
pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
}
#[derive(Subdiagnostic, Clone, Copy)]
#[note(hir_analysis_ty_of_assoc_const_binding_note)]
pub(crate) struct TyOfAssocConstBindingNote<'tcx> {
pub assoc_const: Ident,
pub ty: Ty<'tcx>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding)]
pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> {
#[primary_span]
#[label]
pub span: Span,
pub assoc_const: Ident,
pub var_name: Symbol,
pub var_def_kind: &'static str,
#[label(hir_analysis_var_defined_here_label)]
pub var_defined_here_label: Span,
#[subdiagnostic]
pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
}
#[derive(Subdiagnostic)]
#[help(hir_analysis_parenthesized_fn_trait_expansion)]
pub struct ParenthesizedFnTraitExpansion {

View File

@ -1420,15 +1420,13 @@ impl<'tcx> Pick<'tcx> {
}
_ => {}
}
if tcx.sess.is_nightly_build() {
for (candidate, feature) in &self.unstable_candidates {
lint.help(format!(
"add `#![feature({})]` to the crate attributes to enable `{}`",
feature,
tcx.def_path_str(candidate.item.def_id),
));
}
}
tcx.disabled_nightly_features(
lint,
Some(scope_expr_id),
self.unstable_candidates.iter().map(|(candidate, feature)| {
(format!(" `{}`", tcx.def_path_str(candidate.item.def_id)), *feature)
}),
);
},
);
}

View File

@ -1078,6 +1078,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
feature,
GateIssue::Language,
lint_from_cli,
None,
);
},
);

View File

@ -164,6 +164,19 @@ pub struct ExternalConstraintsData<'tcx> {
// FIXME: implement this.
pub region_constraints: QueryRegionConstraints<'tcx>,
pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
pub normalization_nested_goals: NestedNormalizationGoals<'tcx>,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
pub struct NestedNormalizationGoals<'tcx>(pub Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>);
impl<'tcx> NestedNormalizationGoals<'tcx> {
pub fn empty() -> Self {
NestedNormalizationGoals(vec![])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
// FIXME: Having to clone `region_constraints` for folding feels bad and
@ -183,6 +196,10 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
.iter()
.map(|opaque| opaque.try_fold_with(folder))
.collect::<Result<_, F::Error>>()?,
normalization_nested_goals: self
.normalization_nested_goals
.clone()
.try_fold_with(folder)?,
}))
}
@ -190,6 +207,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
region_constraints: self.region_constraints.clone().fold_with(folder),
opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
normalization_nested_goals: self.normalization_nested_goals.clone().fold_with(folder),
})
}
}
@ -197,7 +215,8 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
try_visit!(self.region_constraints.visit_with(visitor));
self.opaque_types.visit_with(visitor)
try_visit!(self.opaque_types.visit_with(visitor));
self.normalization_nested_goals.visit_with(visitor)
}
}
@ -239,7 +258,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
///
/// This is necessary as we treat nested goals different depending on
/// their source.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeVisitable, TypeFoldable)]
pub enum GoalSource {
Misc,
/// We're proving a where-bound of an impl.
@ -256,12 +275,6 @@ pub enum GoalSource {
ImplWhereBound,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
pub enum IsNormalizesToHack {
Yes,
No,
}
/// Possible ways the given goal can be proven.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CandidateSource {

View File

@ -19,8 +19,8 @@
//! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
use super::{
CandidateSource, Canonical, CanonicalInput, Certainty, Goal, GoalSource, IsNormalizesToHack,
NoSolution, QueryInput, QueryResult,
CandidateSource, Canonical, CanonicalInput, Certainty, Goal, GoalSource, NoSolution,
QueryInput, QueryResult,
};
use crate::{infer::canonical::CanonicalVarValues, ty};
use format::ProofTreeFormatter;
@ -50,7 +50,7 @@ pub type CanonicalState<'tcx, T> = Canonical<'tcx, State<'tcx, T>>;
#[derive(Eq, PartialEq)]
pub enum GoalEvaluationKind<'tcx> {
Root { orig_values: Vec<ty::GenericArg<'tcx>> },
Nested { is_normalizes_to_hack: IsNormalizesToHack },
Nested,
}
#[derive(Eq, PartialEq)]

View File

@ -55,10 +55,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result {
let goal_text = match eval.kind {
GoalEvaluationKind::Root { orig_values: _ } => "ROOT GOAL",
GoalEvaluationKind::Nested { is_normalizes_to_hack } => match is_normalizes_to_hack {
IsNormalizesToHack::No => "GOAL",
IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
},
GoalEvaluationKind::Nested => "GOAL",
};
write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))

View File

@ -43,7 +43,9 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}
#[cfg(parallel_compiler)]
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan};
use rustc_errors::{
Applicability, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
@ -2174,6 +2176,45 @@ impl<'tcx> TyCtxt<'tcx> {
lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
}
/// Find the crate root and the appropriate span where `use` and outer attributes can be
/// inserted at.
pub fn crate_level_attribute_injection_span(self, hir_id: HirId) -> Option<Span> {
for (_hir_id, node) in self.hir().parent_iter(hir_id) {
if let hir::Node::Crate(m) = node {
return Some(m.spans.inject_use_span.shrink_to_lo());
}
}
None
}
pub fn disabled_nightly_features<E: rustc_errors::EmissionGuarantee>(
self,
diag: &mut Diag<'_, E>,
hir_id: Option<HirId>,
features: impl IntoIterator<Item = (String, Symbol)>,
) {
if !self.sess.is_nightly_build() {
return;
}
let span = hir_id.and_then(|id| self.crate_level_attribute_injection_span(id));
for (desc, feature) in features {
// FIXME: make this string translatable
let msg =
format!("add `#![feature({feature})]` to the crate attributes to enable{desc}");
if let Some(span) = span {
diag.span_suggestion_verbose(
span,
msg,
format!("#![feature({feature})]\n"),
Applicability::MachineApplicable,
);
} else {
diag.help(msg);
}
}
}
/// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
/// generated by `#[derive(LintDiagnostic)]`).
#[track_caller]

View File

@ -938,9 +938,6 @@ fn report_non_exhaustive_match<'p, 'tcx>(
};
// In the case of an empty match, replace the '`_` not covered' diagnostic with something more
// informative.
let mut err;
let pattern;
let patterns_len;
if is_empty_match && !non_empty_enum {
return cx.tcx.dcx().emit_err(NonExhaustivePatternsTypeNotEmpty {
cx,
@ -948,33 +945,23 @@ fn report_non_exhaustive_match<'p, 'tcx>(
span: sp,
ty: scrut_ty,
});
} else {
// FIXME: migration of this diagnostic will require list support
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
err = create_e0004(
cx.tcx.sess,
sp,
format!("non-exhaustive patterns: {joined_patterns} not covered"),
);
err.span_label(
sp,
format!(
"pattern{} {} not covered",
rustc_errors::pluralize!(witnesses.len()),
joined_patterns
),
);
patterns_len = witnesses.len();
pattern = if witnesses.len() < 4 {
witnesses
.iter()
.map(|witness| cx.hoist_witness_pat(witness).to_string())
.collect::<Vec<String>>()
.join(" | ")
} else {
"_".to_string()
};
};
}
// FIXME: migration of this diagnostic will require list support
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
let mut err = create_e0004(
cx.tcx.sess,
sp,
format!("non-exhaustive patterns: {joined_patterns} not covered"),
);
err.span_label(
sp,
format!(
"pattern{} {} not covered",
rustc_errors::pluralize!(witnesses.len()),
joined_patterns
),
);
// Point at the definition of non-covered `enum` variants.
if let Some(AdtDefinedHere { adt_def_span, ty, variants }) =
@ -1021,6 +1008,23 @@ fn report_non_exhaustive_match<'p, 'tcx>(
}
}
// Whether we suggest the actual missing patterns or `_`.
let suggest_the_witnesses = witnesses.len() < 4;
let suggested_arm = if suggest_the_witnesses {
let pattern = witnesses
.iter()
.map(|witness| cx.hoist_witness_pat(witness).to_string())
.collect::<Vec<String>>()
.join(" | ");
if witnesses.iter().all(|p| p.is_never_pattern()) && cx.tcx.features().never_patterns {
// Arms with a never pattern don't take a body.
pattern
} else {
format!("{pattern} => todo!()")
}
} else {
format!("_ => todo!()")
};
let mut suggestion = None;
let sm = cx.tcx.sess.source_map();
match arms {
@ -1033,7 +1037,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
};
suggestion = Some((
sp.shrink_to_hi().with_hi(expr_span.hi()),
format!(" {{{indentation}{more}{pattern} => todo!(),{indentation}}}",),
format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",),
));
}
[only] => {
@ -1059,7 +1063,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
};
suggestion = Some((
only.span.shrink_to_hi(),
format!("{comma}{pre_indentation}{pattern} => todo!()"),
format!("{comma}{pre_indentation}{suggested_arm}"),
));
}
[.., prev, last] => {
@ -1082,7 +1086,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
if let Some(spacing) = spacing {
suggestion = Some((
last.span.shrink_to_hi(),
format!("{comma}{spacing}{pattern} => todo!()"),
format!("{comma}{spacing}{suggested_arm}"),
));
}
}
@ -1093,13 +1097,13 @@ fn report_non_exhaustive_match<'p, 'tcx>(
let msg = format!(
"ensure that all possible cases are being handled by adding a match arm with a wildcard \
pattern{}{}",
if patterns_len > 1 && patterns_len < 4 && suggestion.is_some() {
if witnesses.len() > 1 && suggest_the_witnesses && suggestion.is_some() {
", a match arm with multiple or-patterns"
} else {
// we are either not suggesting anything, or suggesting `_`
""
},
match patterns_len {
match witnesses.len() {
// non-exhaustive enum case
0 if suggestion.is_some() => " as shown",
0 => "",

View File

@ -1964,15 +1964,21 @@ fn check_must_not_suspend_ty<'tcx>(
debug!("Checking must_not_suspend for {}", ty);
match *ty.kind() {
ty::Adt(..) if ty.is_box() => {
let boxed_ty = ty.boxed_ty();
let descr_pre = &format!("{}boxed ", data.descr_pre);
ty::Adt(_, args) if ty.is_box() => {
let boxed_ty = args.type_at(0);
let allocator_ty = args.type_at(1);
check_must_not_suspend_ty(
tcx,
boxed_ty,
hir_id,
param_env,
SuspendCheckData { descr_pre, ..data },
SuspendCheckData { descr_pre: &format!("{}boxed ", data.descr_pre), ..data },
) || check_must_not_suspend_ty(
tcx,
allocator_ty,
hir_id,
param_env,
SuspendCheckData { descr_pre: &format!("{}allocator ", data.descr_pre), ..data },
)
}
ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data),

View File

@ -155,16 +155,11 @@ impl<'tcx> CheckConstVisitor<'tcx> {
//
// FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This
// is a pretty narrow case, however.
if tcx.sess.is_nightly_build() {
for gate in missing_secondary {
// FIXME: make this translatable
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
err.help(format!(
"add `#![feature({gate})]` to the crate attributes to enable"
));
}
}
tcx.disabled_nightly_features(
&mut err,
def_id.map(|id| tcx.local_def_id_to_hir_id(id)),
missing_secondary.into_iter().map(|gate| (String::new(), *gate)),
);
err.emit();
}

View File

@ -7,7 +7,6 @@ use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@ -133,16 +132,6 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
return None;
}
if main_def.is_import && !tcx.features().imported_main {
let span = main_def.span;
feature_err(
&tcx.sess,
sym::imported_main,
span,
"using an imported function as entry point `main` is experimental",
)
.emit();
}
return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
}
no_main_err(tcx, visitor);

View File

@ -678,15 +678,19 @@ pub enum Constructor<Cx: PatCx> {
Or,
/// Wildcard pattern.
Wildcard,
/// Never pattern. Only used in `WitnessPat`. An actual never pattern should be lowered as
/// `Wildcard`.
Never,
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively. Also used
/// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
/// for those types for which we cannot list constructors explicitly, like `f64` and `str`. Only
/// used in `WitnessPat`.
NonExhaustive,
/// Fake extra constructor for variants that should not be mentioned in diagnostics.
/// We use this for variants behind an unstable gate as well as
/// `#[doc(hidden)]` ones.
/// Fake extra constructor for variants that should not be mentioned in diagnostics. We use this
/// for variants behind an unstable gate as well as `#[doc(hidden)]` ones. Only used in
/// `WitnessPat`.
Hidden,
/// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
/// top of the file.
/// top of the file. Only used for specialization.
Missing,
/// Fake extra constructor that indicates and empty field that is private. When we encounter one
/// we skip the column entirely so we don't observe its emptiness. Only used for specialization.
@ -708,6 +712,7 @@ impl<Cx: PatCx> Clone for Constructor<Cx> {
Constructor::Str(value) => Constructor::Str(value.clone()),
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
Constructor::Or => Constructor::Or,
Constructor::Never => Constructor::Never,
Constructor::Wildcard => Constructor::Wildcard,
Constructor::NonExhaustive => Constructor::NonExhaustive,
Constructor::Hidden => Constructor::Hidden,
@ -1040,10 +1045,32 @@ impl<Cx: PatCx> ConstructorSet<Cx> {
// In a `MaybeInvalid` place even an empty pattern may be reachable. We therefore
// add a dummy empty constructor here, which will be ignored if the place is
// `ValidOnly`.
missing_empty.push(NonExhaustive);
missing_empty.push(Never);
}
}
SplitConstructorSet { present, missing, missing_empty }
}
/// Whether this set only contains empty constructors.
pub(crate) fn all_empty(&self) -> bool {
match self {
ConstructorSet::Bool
| ConstructorSet::Integers { .. }
| ConstructorSet::Ref
| ConstructorSet::Union
| ConstructorSet::Unlistable => false,
ConstructorSet::NoConstructors => true,
ConstructorSet::Struct { empty } => *empty,
ConstructorSet::Variants { variants, non_exhaustive } => {
!*non_exhaustive
&& variants
.iter()
.all(|visibility| matches!(visibility, VariantVisibility::Empty))
}
ConstructorSet::Slice { array_len, subtype_is_empty } => {
*subtype_is_empty && matches!(array_len, Some(1..))
}
}
}
}

View File

@ -208,6 +208,7 @@ impl<Cx: PatCx> fmt::Debug for DeconstructedPat<Cx> {
}
Ok(())
}
Never => write!(f, "!"),
Wildcard | Missing | NonExhaustive | Hidden | PrivateUninhabited => {
write!(f, "_ : {:?}", pat.ty())
}
@ -311,18 +312,24 @@ impl<Cx: PatCx> WitnessPat<Cx> {
pub(crate) fn new(ctor: Constructor<Cx>, fields: Vec<Self>, ty: Cx::Ty) -> Self {
Self { ctor, fields, ty }
}
pub(crate) fn wildcard(ty: Cx::Ty) -> Self {
Self::new(Wildcard, Vec::new(), ty)
/// Create a wildcard pattern for this type. If the type is empty, we create a `!` pattern.
pub(crate) fn wildcard(cx: &Cx, ty: Cx::Ty) -> Self {
let is_empty = cx.ctors_for_ty(&ty).is_ok_and(|ctors| ctors.all_empty());
let ctor = if is_empty { Never } else { Wildcard };
Self::new(ctor, Vec::new(), ty)
}
/// Construct a pattern that matches everything that starts with this constructor.
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
/// `Some(_)`.
pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
if matches!(ctor, Wildcard) {
return Self::wildcard(cx, ty);
}
let fields = cx
.ctor_sub_tys(&ctor, &ty)
.filter(|(_, PrivateUninhabitedField(skip))| !skip)
.map(|(ty, _)| Self::wildcard(ty))
.map(|(ty, _)| Self::wildcard(cx, ty))
.collect();
Self::new(ctor, fields, ty)
}
@ -334,6 +341,14 @@ impl<Cx: PatCx> WitnessPat<Cx> {
&self.ty
}
pub fn is_never_pattern(&self) -> bool {
match self.ctor() {
Never => true,
Or => self.fields.iter().all(|p| p.is_never_pattern()),
_ => self.fields.iter().any(|p| p.is_never_pattern()),
}
}
pub fn iter_fields(&self) -> impl Iterator<Item = &WitnessPat<Cx>> {
self.fields.iter()
}

View File

@ -247,7 +247,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
},
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
| NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
Or => {
bug!("called `Fields::wildcards` on an `Or` ctor")
}
@ -275,7 +275,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
Ref => 1,
Slice(slice) => slice.arity(),
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
| NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
}
}
@ -824,7 +824,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
}
}
&Str(value) => PatKind::Constant { value },
Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
Never if self.tcx.features().never_patterns => PatKind::Never,
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
Missing { .. } => bug!(
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
`Missing` should have been processed in `apply_constructors`"

View File

@ -24,6 +24,9 @@ session_feature_diagnostic_for_issue =
session_feature_diagnostic_help =
add `#![feature({$feature})]` to the crate attributes to enable
session_feature_diagnostic_suggestion =
add `#![feature({$feature})]` to the crate attributes to enable
session_feature_suggest_upgrade_compiler =
this compiler was built on {$date}; consider upgrading it if it is out of date

View File

@ -54,6 +54,18 @@ pub struct FeatureDiagnosticHelp {
pub feature: Symbol,
}
#[derive(Subdiagnostic)]
#[suggestion(
session_feature_diagnostic_suggestion,
applicability = "maybe-incorrect",
code = "#![feature({feature})]\n"
)]
pub struct FeatureDiagnosticSuggestion {
pub feature: Symbol,
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[help(session_cli_feature_diagnostic_help)]
pub struct CliFeatureDiagnosticHelp {

View File

@ -3,8 +3,8 @@
use crate::config::{Cfg, CheckCfg};
use crate::errors::{
CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
SuggestUpgradeCompiler,
CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp,
FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler,
};
use crate::lint::{
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiag, Lint, LintId,
@ -112,7 +112,7 @@ pub fn feature_err_issue(
}
let mut err = sess.psess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None);
err
}
@ -141,7 +141,7 @@ pub fn feature_warn_issue(
explain: &'static str,
) {
let mut err = sess.psess.dcx.struct_span_warn(span, explain);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None);
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
@ -160,7 +160,7 @@ pub fn add_feature_diagnostics<G: EmissionGuarantee>(
sess: &Session,
feature: Symbol,
) {
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false);
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None);
}
/// Adds the diagnostics for a feature to an existing error.
@ -175,6 +175,7 @@ pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
feature: Symbol,
issue: GateIssue,
feature_from_cli: bool,
inject_span: Option<Span>,
) {
if let Some(n) = find_feature_issue(feature, issue) {
err.subdiagnostic(sess.dcx(), FeatureDiagnosticForIssue { n });
@ -184,6 +185,8 @@ pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
if sess.psess.unstable_features.is_nightly_build() {
if feature_from_cli {
err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature });
} else if let Some(span) = inject_span {
err.subdiagnostic(sess.dcx(), FeatureDiagnosticSuggestion { feature, span });
} else {
err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature });
}

View File

@ -21,8 +21,9 @@
//! However, if `?fresh_var` ends up geteting equated to another type, we retry the
//! `NormalizesTo` goal, at which point the opaque is actually defined.
use super::{EvalCtxt, GoalSource};
use super::EvalCtxt;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::GoalSource;
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
use rustc_middle::ty::{self, Ty};
@ -121,10 +122,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
ty::TermKind::Const(_) => {
if let Some(alias) = term.to_alias_ty(self.tcx()) {
let term = self.next_term_infer_of_kind(term);
self.add_goal(
GoalSource::Misc,
Goal::new(self.tcx(), param_env, ty::NormalizesTo { alias, term }),
);
self.add_normalizes_to_goal(Goal::new(
self.tcx(),
param_env,
ty::NormalizesTo { alias, term },
));
self.try_evaluate_added_goals()?;
Ok(Some(self.resolve_vars_if_possible(term)))
} else {
@ -145,18 +147,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
return None;
}
let ty::Alias(_, alias) = *ty.kind() else {
let ty::Alias(kind, alias) = *ty.kind() else {
return Some(ty);
};
match self.commit_if_ok(|this| {
let tcx = this.tcx();
let normalized_ty = this.next_ty_infer();
let normalizes_to_goal = Goal::new(
this.tcx(),
param_env,
ty::NormalizesTo { alias, term: normalized_ty.into() },
);
this.add_goal(GoalSource::Misc, normalizes_to_goal);
let normalizes_to = ty::NormalizesTo { alias, term: normalized_ty.into() };
match kind {
ty::AliasKind::Opaque => {
// HACK: Unlike for associated types, `normalizes-to` for opaques
// is currently not treated as a function. We do not erase the
// expected term.
this.add_goal(GoalSource::Misc, Goal::new(tcx, param_env, normalizes_to));
}
ty::AliasKind::Projection | ty::AliasKind::Inherent | ty::AliasKind::Weak => {
this.add_normalizes_to_goal(Goal::new(tcx, param_env, normalizes_to))
}
}
this.try_evaluate_added_goals()?;
Ok(this.resolve_vars_if_possible(normalized_ty))
}) {

View File

@ -9,6 +9,7 @@
//!
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
use crate::solve::eval_ctxt::NestedGoals;
use crate::solve::{
inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
};
@ -19,6 +20,7 @@ use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
use rustc_infer::infer::resolve::EagerResolver;
use rustc_infer::infer::{InferCtxt, InferOk};
use rustc_infer::traits::solve::NestedNormalizationGoals;
use rustc_middle::infer::canonical::Canonical;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{
@ -28,6 +30,7 @@ use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer};
use rustc_span::DUMMY_SP;
use std::assert_matches::assert_matches;
use std::iter;
use std::ops::Deref;
@ -93,13 +96,31 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
previous call to `try_evaluate_added_goals!`"
);
let certainty = certainty.unify_with(goals_certainty);
let var_values = self.var_values;
let external_constraints = self.compute_external_query_constraints()?;
// When normalizing, we've replaced the expected term with an unconstrained
// inference variable. This means that we dropped information which could
// have been important. We handle this by instead returning the nested goals
// to the caller, where they are then handled.
//
// As we return all ambiguous nested goals, we can ignore the certainty returned
// by `try_evaluate_added_goals()`.
let (certainty, normalization_nested_goals) = if self.is_normalizes_to_goal {
let NestedGoals { normalizes_to_goals, goals } = std::mem::take(&mut self.nested_goals);
if cfg!(debug_assertions) {
assert!(normalizes_to_goals.is_empty());
if goals.is_empty() {
assert_matches!(goals_certainty, Certainty::Yes);
}
}
(certainty, NestedNormalizationGoals(goals))
} else {
let certainty = certainty.unify_with(goals_certainty);
(certainty, NestedNormalizationGoals::empty())
};
let external_constraints =
self.compute_external_query_constraints(normalization_nested_goals)?;
let (var_values, mut external_constraints) =
(var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
(self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
// Remove any trivial region constraints once we've resolved regions
external_constraints
.region_constraints
@ -146,6 +167,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
fn compute_external_query_constraints(
&self,
normalization_nested_goals: NestedNormalizationGoals<'tcx>,
) -> Result<ExternalConstraintsData<'tcx>, NoSolution> {
// We only check for leaks from universes which were entered inside
// of the query.
@ -176,7 +198,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
});
Ok(ExternalConstraintsData { region_constraints, opaque_types })
Ok(ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals })
}
/// After calling a canonical query, we apply the constraints returned
@ -185,13 +207,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
/// This happens in three steps:
/// - we instantiate the bound variables of the query response
/// - we unify the `var_values` of the response with the `original_values`
/// - we apply the `external_constraints` returned by the query
/// - we apply the `external_constraints` returned by the query, returning
/// the `normalization_nested_goals`
pub(super) fn instantiate_and_apply_query_response(
&mut self,
param_env: ty::ParamEnv<'tcx>,
original_values: Vec<ty::GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>,
) -> Certainty {
) -> (NestedNormalizationGoals<'tcx>, Certainty) {
let instantiation = Self::compute_query_response_instantiation_values(
self.infcx,
&original_values,
@ -203,11 +226,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
Self::unify_query_var_values(self.infcx, param_env, &original_values, var_values);
let ExternalConstraintsData { region_constraints, opaque_types } =
external_constraints.deref();
let ExternalConstraintsData {
region_constraints,
opaque_types,
normalization_nested_goals,
} = external_constraints.deref();
self.register_region_constraints(region_constraints);
self.register_new_opaque_types(param_env, opaque_types);
certainty
(normalization_nested_goals.clone(), certainty)
}
/// This returns the canoncial variable values to instantiate the bound variables of

View File

@ -11,6 +11,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
infcx: self.infcx,
variables: self.variables,
var_values: self.var_values,
is_normalizes_to_goal: self.is_normalizes_to_goal,
predefined_opaques_in_body: self.predefined_opaques_in_body,
max_input_universe: self.max_input_universe,
search_graph: self.search_graph,
@ -25,6 +26,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
infcx: _,
variables: _,
var_values: _,
is_normalizes_to_goal: _,
predefined_opaques_in_body: _,
max_input_universe: _,
search_graph: _,

View File

@ -7,14 +7,14 @@ use rustc_infer::infer::{
BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::MaybeCause;
use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::canonical::CanonicalVarInfos;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::solve::inspect;
use rustc_middle::traits::solve::{
CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, PredefinedOpaques,
PredefinedOpaquesData, QueryResult,
CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaques, PredefinedOpaquesData,
QueryResult,
};
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::{
@ -61,6 +61,14 @@ pub struct EvalCtxt<'a, 'tcx> {
/// The variable info for the `var_values`, only used to make an ambiguous response
/// with no constraints.
variables: CanonicalVarInfos<'tcx>,
/// Whether we're currently computing a `NormalizesTo` goal. Unlike other goals,
/// `NormalizesTo` goals act like functions with the expected term always being
/// fully unconstrained. This would weaken inference however, as the nested goals
/// never get the inference constraints from the actual normalized-to type. Because
/// of this we return any ambiguous nested goals from `NormalizesTo` to the caller
/// when then adds these to its own context. The caller is always an `AliasRelate`
/// goal so this never leaks out of the solver.
is_normalizes_to_goal: bool,
pub(super) var_values: CanonicalVarValues<'tcx>,
predefined_opaques_in_body: PredefinedOpaques<'tcx>,
@ -91,9 +99,9 @@ pub struct EvalCtxt<'a, 'tcx> {
pub(super) inspect: ProofTreeBuilder<'tcx>,
}
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub(super) struct NestedGoals<'tcx> {
/// This normalizes-to goal that is treated specially during the evaluation
/// These normalizes-to goals are treated specially during the evaluation
/// loop. In each iteration we take the RHS of the projection, replace it with
/// a fresh inference variable, and only after evaluating that goal do we
/// equate the fresh inference variable with the actual RHS of the predicate.
@ -101,26 +109,24 @@ pub(super) struct NestedGoals<'tcx> {
/// This is both to improve caching, and to avoid using the RHS of the
/// projection predicate to influence the normalizes-to candidate we select.
///
/// This is not a 'real' nested goal. We must not forget to replace the RHS
/// with a fresh inference variable when we evaluate this goal. That can result
/// in a trait solver cycle. This would currently result in overflow but can be
/// can be unsound with more powerful coinduction in the future.
pub(super) normalizes_to_hack_goal: Option<Goal<'tcx, ty::NormalizesTo<'tcx>>>,
/// Forgetting to replace the RHS with a fresh inference variable when we evaluate
/// this goal results in an ICE..
pub(super) normalizes_to_goals: Vec<Goal<'tcx, ty::NormalizesTo<'tcx>>>,
/// The rest of the goals which have not yet processed or remain ambiguous.
pub(super) goals: Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
}
impl<'tcx> NestedGoals<'tcx> {
pub(super) fn new() -> Self {
Self { normalizes_to_hack_goal: None, goals: Vec::new() }
Self { normalizes_to_goals: Vec::new(), goals: Vec::new() }
}
pub(super) fn is_empty(&self) -> bool {
self.normalizes_to_hack_goal.is_none() && self.goals.is_empty()
self.normalizes_to_goals.is_empty() && self.goals.is_empty()
}
pub(super) fn extend(&mut self, other: NestedGoals<'tcx>) {
assert_eq!(other.normalizes_to_hack_goal, None);
self.normalizes_to_goals.extend(other.normalizes_to_goals);
self.goals.extend(other.goals)
}
}
@ -155,6 +161,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
self.search_graph.solver_mode()
}
pub(super) fn set_is_normalizes_to_goal(&mut self) {
self.is_normalizes_to_goal = true;
}
/// Creates a root evaluation context and search graph. This should only be
/// used from outside of any evaluation, and other methods should be preferred
/// over using this manually (such as [`InferCtxtEvalExt::evaluate_root_goal`]).
@ -167,8 +177,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let mut search_graph = search_graph::SearchGraph::new(mode);
let mut ecx = EvalCtxt {
search_graph: &mut search_graph,
infcx,
search_graph: &mut search_graph,
nested_goals: NestedGoals::new(),
inspect: ProofTreeBuilder::new_maybe_root(infcx.tcx, generate_proof_tree),
@ -180,6 +190,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
max_input_universe: ty::UniverseIndex::ROOT,
variables: ty::List::empty(),
var_values: CanonicalVarValues::dummy(),
is_normalizes_to_goal: false,
tainted: Ok(()),
};
let result = f(&mut ecx);
@ -233,6 +244,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
infcx,
variables: canonical_input.variables,
var_values,
is_normalizes_to_goal: false,
predefined_opaques_in_body: input.predefined_opaques_in_body,
max_input_universe: canonical_input.max_universe,
search_graph,
@ -319,6 +331,27 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
source: GoalSource,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
) -> Result<(bool, Certainty), NoSolution> {
let (normalization_nested_goals, has_changed, certainty) =
self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?;
assert!(normalization_nested_goals.is_empty());
Ok((has_changed, certainty))
}
/// Recursively evaluates `goal`, returning the nested goals in case
/// the nested goal is a `NormalizesTo` goal.
///
/// As all other goal kinds do not return any nested goals and
/// `NormalizesTo` is only used by `AliasRelate`, all other callsites
/// should use [`EvalCtxt::evaluate_goal`] which discards that empty
/// storage.
// FIXME(-Znext-solver=coinduction): `_source` is currently unused but will
// be necessary once we implement the new coinduction approach.
fn evaluate_goal_raw(
&mut self,
goal_evaluation_kind: GoalEvaluationKind,
_source: GoalSource,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
) -> Result<(NestedNormalizationGoals<'tcx>, bool, Certainty), NoSolution> {
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
let mut goal_evaluation =
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
@ -336,12 +369,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
Ok(response) => response,
};
let (certainty, has_changed) = self.instantiate_response_discarding_overflow(
goal.param_env,
source,
orig_values,
canonical_response,
);
let (normalization_nested_goals, certainty, has_changed) = self
.instantiate_response_discarding_overflow(
goal.param_env,
orig_values,
canonical_response,
);
self.inspect.goal_evaluation(goal_evaluation);
// FIXME: We previously had an assert here that checked that recomputing
// a goal after applying its constraints did not change its response.
@ -353,47 +386,25 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// Once we have decided on how to handle trait-system-refactor-initiative#75,
// we should re-add an assert here.
Ok((has_changed, certainty))
Ok((normalization_nested_goals, has_changed, certainty))
}
fn instantiate_response_discarding_overflow(
&mut self,
param_env: ty::ParamEnv<'tcx>,
source: GoalSource,
original_values: Vec<ty::GenericArg<'tcx>>,
response: CanonicalResponse<'tcx>,
) -> (Certainty, bool) {
// The old solver did not evaluate nested goals when normalizing.
// It returned the selection constraints allowing a `Projection`
// obligation to not hold in coherence while avoiding the fatal error
// from overflow.
//
// We match this behavior here by considering all constraints
// from nested goals which are not from where-bounds. We will already
// need to track which nested goals are required by impl where-bounds
// for coinductive cycles, so we simply reuse that here.
//
// While we could consider overflow constraints in more cases, this should
// not be necessary for backcompat and results in better perf. It also
// avoids a potential inconsistency which would otherwise require some
// tracking for root goals as well. See #119071 for an example.
let keep_overflow_constraints = || {
self.search_graph.current_goal_is_normalizes_to()
&& source != GoalSource::ImplWhereBound
};
if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty
&& !keep_overflow_constraints()
{
return (response.value.certainty, false);
) -> (NestedNormalizationGoals<'tcx>, Certainty, bool) {
if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty {
return (NestedNormalizationGoals::empty(), response.value.certainty, false);
}
let has_changed = !response.value.var_values.is_identity_modulo_regions()
|| !response.value.external_constraints.opaque_types.is_empty();
let certainty =
let (normalization_nested_goals, certainty) =
self.instantiate_and_apply_query_response(param_env, original_values, response);
(certainty, has_changed)
(normalization_nested_goals, certainty, has_changed)
}
fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult<'tcx> {
@ -496,7 +507,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
/// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
let tcx = self.tcx();
let mut goals = core::mem::replace(&mut self.nested_goals, NestedGoals::new());
let mut goals = core::mem::take(&mut self.nested_goals);
self.inspect.evaluate_added_goals_loop_start();
@ -508,7 +519,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// If this loop did not result in any progress, what's our final certainty.
let mut unchanged_certainty = Some(Certainty::Yes);
if let Some(goal) = goals.normalizes_to_hack_goal.take() {
for goal in goals.normalizes_to_goals {
// Replace the goal with an unconstrained infer var, so the
// RHS does not affect projection candidate assembly.
let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term);
@ -517,11 +528,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs },
);
let (_, certainty) = self.evaluate_goal(
GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::Yes },
let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
GoalEvaluationKind::Nested,
GoalSource::Misc,
unconstrained_goal,
)?;
// Add the nested goals from normalization to our own nested goals.
goals.goals.extend(nested_goals);
// Finally, equate the goal's RHS with the unconstrained var.
// We put the nested goals from this into goals instead of
@ -536,27 +549,23 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// looking at the "has changed" return from evaluate_goal,
// because we expect the `unconstrained_rhs` part of the predicate
// to have changed -- that means we actually normalized successfully!
if goal.predicate.alias != self.resolve_vars_if_possible(goal.predicate.alias) {
let with_resolved_vars = self.resolve_vars_if_possible(goal);
if goal.predicate.alias != with_resolved_vars.predicate.alias {
unchanged_certainty = None;
}
match certainty {
Certainty::Yes => {}
Certainty::Maybe(_) => {
// We need to resolve vars here so that we correctly
// deal with `has_changed` in the next iteration.
self.set_normalizes_to_hack_goal(self.resolve_vars_if_possible(goal));
self.nested_goals.normalizes_to_goals.push(with_resolved_vars);
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
}
}
}
for (source, goal) in goals.goals.drain(..) {
let (has_changed, certainty) = self.evaluate_goal(
GoalEvaluationKind::Nested { is_normalizes_to_hack: IsNormalizesToHack::No },
source,
goal,
)?;
for (source, goal) in goals.goals {
let (has_changed, certainty) =
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
if has_changed {
unchanged_certainty = None;
}

View File

@ -24,6 +24,7 @@ where
infcx: outer_ecx.infcx,
variables: outer_ecx.variables,
var_values: outer_ecx.var_values,
is_normalizes_to_goal: outer_ecx.is_normalizes_to_goal,
predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body,
max_input_universe: outer_ecx.max_input_universe,
search_graph: outer_ecx.search_graph,

View File

@ -58,12 +58,13 @@ impl<'tcx> InferCtxt<'tcx> {
}
let candidate = candidates.pop().unwrap();
let certainty = ecx.instantiate_and_apply_query_response(
trait_goal.param_env,
orig_values,
candidate.result,
);
let (normalization_nested_goals, certainty) = ecx
.instantiate_and_apply_query_response(
trait_goal.param_env,
orig_values,
candidate.result,
);
assert!(normalization_nested_goals.is_empty());
Ok(Some((candidate, certainty)))
});

View File

@ -70,7 +70,19 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
instantiated_goals.push(goal);
}
for &goal in &instantiated_goals {
for goal in instantiated_goals.iter().copied() {
// We need to be careful with `NormalizesTo` goals as the
// expected term has to be replaced with an unconstrained
// inference variable.
if let Some(kind) = goal.predicate.kind().no_bound_vars()
&& let ty::PredicateKind::NormalizesTo(predicate) = kind
&& !predicate.alias.is_opaque(infcx.tcx)
{
// FIXME: We currently skip these goals as
// `fn evaluate_root_goal` ICEs if there are any
// `NestedNormalizationGoals`.
continue;
};
let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
let proof_tree = proof_tree.unwrap();
try_visit!(visitor.visit_goal(&InspectGoal::new(

View File

@ -7,7 +7,7 @@ use std::mem;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalInput, Certainty, Goal, GoalSource, IsNormalizesToHack, QueryInput, QueryResult,
CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult,
};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::DumpSolverProofTree;
@ -97,9 +97,7 @@ impl<'tcx> WipGoalEvaluation<'tcx> {
WipGoalEvaluationKind::Root { orig_values } => {
inspect::GoalEvaluationKind::Root { orig_values }
}
WipGoalEvaluationKind::Nested { is_normalizes_to_hack } => {
inspect::GoalEvaluationKind::Nested { is_normalizes_to_hack }
}
WipGoalEvaluationKind::Nested => inspect::GoalEvaluationKind::Nested,
},
evaluation: self.evaluation.unwrap().finalize(),
}
@ -109,7 +107,7 @@ impl<'tcx> WipGoalEvaluation<'tcx> {
#[derive(Eq, PartialEq, Debug)]
pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> {
Root { orig_values: Vec<ty::GenericArg<'tcx>> },
Nested { is_normalizes_to_hack: IsNormalizesToHack },
Nested,
}
#[derive(Eq, PartialEq)]
@ -305,9 +303,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
solve::GoalEvaluationKind::Root => {
WipGoalEvaluationKind::Root { orig_values: orig_values.to_vec() }
}
solve::GoalEvaluationKind::Nested { is_normalizes_to_hack } => {
WipGoalEvaluationKind::Nested { is_normalizes_to_hack }
}
solve::GoalEvaluationKind::Nested => WipGoalEvaluationKind::Nested,
},
evaluation: None,
})
@ -419,6 +415,17 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
pub fn add_normalizes_to_goal(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
) {
if ecx.inspect.is_noop() {
return;
}
Self::add_goal(ecx, GoalSource::Misc, goal.with(ecx.tcx(), goal.predicate));
}
pub fn add_goal(
ecx: &mut EvalCtxt<'_, 'tcx>,
source: GoalSource,

View File

@ -18,8 +18,7 @@ use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::infer::canonical::CanonicalVarInfos;
use rustc_middle::traits::solve::{
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, IsNormalizesToHack,
QueryResult, Response,
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, QueryResult, Response,
};
use rustc_middle::ty::{self, AliasRelationDirection, Ty, TyCtxt, UniverseIndex};
use rustc_middle::ty::{
@ -69,7 +68,7 @@ enum SolverMode {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum GoalEvaluationKind {
Root,
Nested { is_normalizes_to_hack: IsNormalizesToHack },
Nested,
}
#[extension(trait CanonicalResponseExt)]
@ -202,12 +201,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
impl<'tcx> EvalCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn set_normalizes_to_hack_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
assert!(
self.nested_goals.normalizes_to_hack_goal.is_none(),
"attempted to set the projection eq hack goal when one already exists"
);
self.nested_goals.normalizes_to_hack_goal = Some(goal);
fn add_normalizes_to_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
inspect::ProofTreeBuilder::add_normalizes_to_goal(self, goal);
self.nested_goals.normalizes_to_goals.push(goal);
}
#[instrument(level = "debug", skip(self))]

View File

@ -16,7 +16,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
.no_bound_vars()
.expect("const ty should not rely on other generics"),
) {
self.eq(goal.param_env, normalized_const, goal.predicate.term.ct().unwrap())?;
self.instantiate_normalizes_to_term(goal, normalized_const.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)

View File

@ -16,7 +16,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> QueryResult<'tcx> {
let tcx = self.tcx();
let inherent = goal.predicate.alias;
let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
let impl_def_id = tcx.parent(inherent.def_id);
let impl_args = self.fresh_args_for_item(impl_def_id);
@ -30,12 +29,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// Equate IAT with the RHS of the project goal
let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, tcx);
self.eq(
goal.param_env,
expected,
tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args),
)
.expect("expected goal term to be fully unconstrained");
// Check both where clauses on the impl and IAT
//
@ -51,6 +44,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
.map(|(pred, _)| goal.with(tcx, pred)),
);
let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args);
self.instantiate_normalizes_to_term(goal, normalized.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}

View File

@ -31,32 +31,19 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, NormalizesTo<'tcx>>,
) -> QueryResult<'tcx> {
let def_id = goal.predicate.def_id();
let def_kind = self.tcx().def_kind(def_id);
match def_kind {
DefKind::OpaqueTy => return self.normalize_opaque_type(goal),
_ => self.set_is_normalizes_to_goal(),
}
debug_assert!(self.term_is_fully_unconstrained(goal));
match self.tcx().def_kind(def_id) {
DefKind::AssocTy | DefKind::AssocConst => {
match self.tcx().associated_item(def_id).container {
ty::AssocItemContainer::TraitContainer => {
// To only compute normalization once for each projection we only
// assemble normalization candidates if the expected term is an
// unconstrained inference variable.
//
// Why: For better cache hits, since if we have an unconstrained RHS then
// there are only as many cache keys as there are (canonicalized) alias
// types in each normalizes-to goal. This also weakens inference in a
// forwards-compatible way so we don't use the value of the RHS term to
// affect candidate assembly for projections.
//
// E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
// `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
// `U` and equate it with `u32`. This means that we don't need a separate
// projection cache in the solver, since we're piggybacking off of regular
// goal caching.
if self.term_is_fully_unconstrained(goal) {
let candidates = self.assemble_and_evaluate_candidates(goal);
self.merge_candidates(candidates)
} else {
self.set_normalizes_to_hack_goal(goal);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
let candidates = self.assemble_and_evaluate_candidates(goal);
self.merge_candidates(candidates)
}
ty::AssocItemContainer::ImplContainer => {
self.normalize_inherent_associated_type(goal)
@ -64,9 +51,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
DefKind::AnonConst => self.normalize_anon_const(goal),
DefKind::OpaqueTy => self.normalize_opaque_type(goal),
DefKind::TyAlias => self.normalize_weak_type(goal),
kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)),
kind => bug!("unknown DefKind {} in normalizes-to goal: {goal:#?}", kind.descr(def_id)),
}
}

View File

@ -15,10 +15,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> QueryResult<'tcx> {
let tcx = self.tcx();
let weak_ty = goal.predicate.alias;
let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
self.eq(goal.param_env, expected, actual)?;
// Check where clauses
self.add_goals(
@ -30,6 +26,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
.map(|pred| goal.with(tcx, pred)),
);
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
self.instantiate_normalizes_to_term(goal, actual.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}

View File

@ -10,7 +10,6 @@ use rustc_index::IndexVec;
use rustc_middle::dep_graph::dep_kinds;
use rustc_middle::traits::solve::CacheData;
use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult};
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_session::Limit;
use std::mem;
@ -175,15 +174,6 @@ impl<'tcx> SearchGraph<'tcx> {
}
}
pub(super) fn current_goal_is_normalizes_to(&self) -> bool {
self.stack.raw.last().map_or(false, |e| {
matches!(
e.input.value.goal.predicate.kind().skip_binder(),
ty::PredicateKind::NormalizesTo(..)
)
})
}
/// Returns the remaining depth allowed for nested goals.
///
/// This is generally simply one less than the current depth.

View File

@ -3510,9 +3510,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::TrivialBound => {
err.help("see issue #48214");
if tcx.sess.opts.unstable_features.is_nightly_build() {
err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
}
tcx.disabled_nightly_features(
err,
Some(tcx.local_def_id_to_hir_id(body_id)),
[(String::new(), sym::trivial_bounds)],
);
}
ObligationCauseCode::OpaqueReturnType(expr_info) => {
if let Some((expr_ty, expr_span)) = expr_info {

View File

@ -148,19 +148,20 @@ pub enum PredicateKind<I: Interner> {
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
Ambiguous,
/// The alias normalizes to `term`. Unlike `Projection`, this always fails if the alias
/// cannot be normalized in the current context.
/// This should only be used inside of the new solver for `AliasRelate` and expects
/// the `term` to be an unconstrained inference variable.
///
/// `Projection(<T as Trait>::Assoc, ?x)` results in `?x == <T as Trait>::Assoc` while
/// `NormalizesTo(<T as Trait>::Assoc, ?x)` results in `NoSolution`.
///
/// Only used in the new solver.
/// The alias normalizes to `term`. Unlike `Projection`, this always fails if the
/// alias cannot be normalized in the current context. For the rigid alias
/// `T as Trait>::Assoc`, `Projection(<T as Trait>::Assoc, ?x)` constrains `?x`
/// to `<T as Trait>::Assoc` while `NormalizesTo(<T as Trait>::Assoc, ?x)`
/// results in `NoSolution`.
NormalizesTo(I::NormalizesTo),
/// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
/// This predicate requires two terms to be equal to eachother.
///
/// Only used for new solver
/// Only used for new solver.
AliasRelate(I::Term, I::Term, AliasRelationDirection),
}

View File

@ -1462,7 +1462,7 @@ impl<T, A: Allocator> Vec<T, A> {
///
/// The removed element is replaced by the last element of the vector.
///
/// This does not preserve ordering, but is *O*(1).
/// This does not preserve ordering of the remaining elements, but is *O*(1).
/// If you need to preserve the element order, use [`remove`] instead.
///
/// [`remove`]: Vec::remove

View File

@ -71,6 +71,8 @@ use crate::ascii::Char as AsciiChar;
///
/// You cannot use the `#[default]` attribute on non-unit or non-exhaustive variants.
///
/// The `#[default]` attribute was stabilized in Rust 1.62.0.
///
/// ## How can I implement `Default`?
///
/// Provide an implementation for the `default()` method that returns the value of

View File

@ -136,6 +136,28 @@ h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
h3 a:link, h3 a:visited, h4 a:link, h4 a:visited,
h5 a:link, h5 a:visited {color: black;}
h1, h2, h3, h4, h5 {
/* This is needed to be able to position the doc-anchor. Ideally there
would be a <div> around the whole document, but we don't have that. */
position: relative;
}
a.doc-anchor {
color: black;
display: none;
position: absolute;
left: -20px;
/* We add this padding so that when the cursor moves from the heading's text to the anchor,
the anchor doesn't disappear. */
padding-right: 5px;
/* And this padding is used to make the anchor larger and easier to click on. */
padding-left: 3px;
}
*:hover > .doc-anchor {
display: block;
}
/* Code */
pre, code {

View File

@ -52,7 +52,7 @@
- [powerpc64-ibm-aix](platform-support/aix.md)
- [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [riscv32*-unknown-none-elf](platform-support/riscv32imac-unknown-none-elf.md)
- [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)

View File

@ -167,11 +167,11 @@ target | std | notes
[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI)
[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI)
[`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
[`riscv32imac-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
[`riscv32i-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA)
[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA)
[`riscv32imc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
[`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
[`riscv32i-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA)
[`riscv32im-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA)
[`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
[`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)

View File

@ -1 +0,0 @@
riscv32imac-unknown-none-elf.md

View File

@ -1 +0,0 @@
riscv32imac-unknown-none-elf.md

View File

@ -1 +0,0 @@
riscv32imac-unknown-none-elf.md

View File

@ -1 +0,0 @@
riscv32imac-unknown-none-elf.md

View File

@ -75,6 +75,7 @@ pub(crate) fn look_for_custom_classes<'tcx>(cx: &DocContext<'tcx>, item: &Item)
sym::custom_code_classes_in_docs,
GateIssue::Language,
false,
None,
);
err.note(

View File

@ -1,3 +1 @@
#![feature(imported_main)]
use cargo_miri_test::main;

View File

@ -1,5 +1,3 @@
#![feature(imported_main)]
pub mod foo {
pub fn mymain() {
println!("Hello, world!");

View File

@ -1,5 +1,3 @@
#![feature(imported_main)]
mod foo {
pub(crate) fn bar() {}
}

View File

@ -0,0 +1,25 @@
// Check that we eventually catch types of assoc const bounds
// (containing late-bound vars) that are ill-formed.
#![feature(associated_const_equality)]
trait Trait<T> {
const K: T;
}
fn take(
_: impl Trait<
<<for<'a> fn(&'a str) -> &'a str as Project>::Out as Discard>::Out,
K = { () }
>,
) {}
//~^^^^^^ ERROR implementation of `Project` is not general enough
//~^^^^ ERROR higher-ranked subtype error
//~| ERROR higher-ranked subtype error
trait Project { type Out; }
impl<T> Project for fn(T) -> T { type Out = T; }
trait Discard { type Out; }
impl<T: ?Sized> Discard for T { type Out = (); }
fn main() {}

View File

@ -0,0 +1,25 @@
error: higher-ranked subtype error
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
|
LL | K = { () }
| ^^^^^^
error: higher-ranked subtype error
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
|
LL | K = { () }
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: implementation of `Project` is not general enough
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:9:4
|
LL | fn take(
| ^^^^ implementation of `Project` is not general enough
|
= note: `Project` would have to be implemented for the type `for<'a> fn(&'a str) -> &'a str`
= note: ...but `Project` is actually implemented for the type `fn(&'0 str) -> &'0 str`, for some specific lifetime `'0`
error: aborting due to 3 previous errors

View File

@ -0,0 +1,22 @@
// Check that we don't reject non-escaping late-bound vars in the type of assoc const bindings.
// There's no reason why we should disallow them.
//
//@ check-pass
#![feature(associated_const_equality)]
trait Trait<T> {
const K: T;
}
fn take(
_: impl Trait<
<for<'a> fn(&'a str) -> &'a str as Discard>::Out,
K = { () }
>,
) {}
trait Discard { type Out; }
impl<T: ?Sized> Discard for T { type Out = (); }
fn main() {}

View File

@ -0,0 +1,15 @@
// Detect and reject escaping late-bound generic params in
// the type of assoc consts used in an equality bound.
#![feature(associated_const_equality)]
trait Trait<'a> {
const K: &'a ();
}
fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
//~^ ERROR the type of the associated constant `K` cannot capture late-bound generic parameters
//~| NOTE its type cannot capture the late-bound lifetime parameter `'r`
//~| NOTE the late-bound lifetime parameter `'r` is defined here
//~| NOTE `K` has type `&'r ()`
fn main() {}

View File

@ -0,0 +1,12 @@
error: the type of the associated constant `K` cannot capture late-bound generic parameters
--> $DIR/assoc-const-eq-esc-bound-var-in-ty.rs:9:35
|
LL | fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
| -- ^ its type cannot capture the late-bound lifetime parameter `'r`
| |
| the late-bound lifetime parameter `'r` is defined here
|
= note: `K` has type `&'r ()`
error: aborting due to 1 previous error

View File

@ -0,0 +1,55 @@
// Regression test for issue #108271.
// Detect and reject generic params in the type of assoc consts used in an equality bound.
#![feature(associated_const_equality)]
trait Trait<'a, T: 'a, const N: usize> {
const K: &'a [T; N];
}
fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
//~| NOTE its type must not depend on the lifetime parameter `'r`
//~| NOTE the lifetime parameter `'r` is defined here
//~| NOTE `K` has type `&'r [A; Q]`
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
//~| NOTE its type must not depend on the type parameter `A`
//~| NOTE the type parameter `A` is defined here
//~| NOTE `K` has type `&'r [A; Q]`
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
//~| NOTE its type must not depend on the const parameter `Q`
//~| NOTE the const parameter `Q` is defined here
//~| NOTE `K` has type `&'r [A; Q]`
trait Project {
const SELF: Self;
}
fn take1(_: impl Project<SELF = {}>) {}
//~^ ERROR the type of the associated constant `SELF` must not depend on `impl Trait`
//~| NOTE its type must not depend on `impl Trait`
//~| NOTE the `impl Trait` is specified here
fn take2<P: Project<SELF = {}>>(_: P) {}
//~^ ERROR the type of the associated constant `SELF` must not depend on generic parameters
//~| NOTE its type must not depend on the type parameter `P`
//~| NOTE the type parameter `P` is defined here
//~| NOTE `SELF` has type `P`
trait Iface<'r> {
//~^ NOTE the lifetime parameter `'r` is defined here
type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
//~| NOTE its type must not depend on the lifetime parameter `'r`
//~| NOTE `K` has type `&'r [Self; Q]`
//~| ERROR the type of the associated constant `K` must not depend on `Self`
//~| NOTE its type must not depend on `Self`
//~| NOTE `K` has type `&'r [Self; Q]`
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
//~| NOTE its type must not depend on the const parameter `Q`
//~| NOTE the const parameter `Q` is defined here
//~| NOTE `K` has type `&'r [Self; Q]`
where
Self: Sized + 'r;
}
fn main() {}

View File

@ -0,0 +1,76 @@
error: the type of the associated constant `K` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
| -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
|
= note: `K` has type `&'r [A; Q]`
error: the type of the associated constant `K` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
| - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
|
= note: `K` has type `&'r [A; Q]`
error: the type of the associated constant `K` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
| - ^ its type must not depend on the const parameter `Q`
| |
| the const parameter `Q` is defined here
|
= note: `K` has type `&'r [A; Q]`
error: the type of the associated constant `SELF` must not depend on `impl Trait`
--> $DIR/assoc-const-eq-param-in-ty.rs:27:26
|
LL | fn take1(_: impl Project<SELF = {}>) {}
| -------------^^^^------
| | |
| | its type must not depend on `impl Trait`
| the `impl Trait` is specified here
error: the type of the associated constant `SELF` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:32:21
|
LL | fn take2<P: Project<SELF = {}>>(_: P) {}
| - ^^^^ its type must not depend on the type parameter `P`
| |
| the type parameter `P` is defined here
|
= note: `SELF` has type `P`
error: the type of the associated constant `K` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
LL | trait Iface<'r> {
| -- the lifetime parameter `'r` is defined here
LL |
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
| ^ its type must not depend on the lifetime parameter `'r`
|
= note: `K` has type `&'r [Self; Q]`
error: the type of the associated constant `K` must not depend on `Self`
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
| ^ its type must not depend on `Self`
|
= note: `K` has type `&'r [Self; Q]`
error: the type of the associated constant `K` must not depend on generic parameters
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
| - ^ its type must not depend on the const parameter `Q`
| |
| the const parameter `Q` is defined here
|
= note: `K` has type `&'r [Self; Q]`
error: aborting due to 8 previous errors

View File

@ -36,8 +36,11 @@ LL | field2: SafeEnum::Variant4("str".to_string()),
| ^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:96:5

View File

@ -5,11 +5,16 @@
// Can never be used as const generics.
fn uwu_0<const N: &'static mut ()>() {}
//~^ ERROR: forbidden as the type of a const generic
//~| HELP: add `#![feature(adt_const_params)]`
//~| HELP: add `#![feature(adt_const_params)]`
//~| HELP: add `#![feature(adt_const_params)]`
//~| HELP: add `#![feature(adt_const_params)]`
//~| HELP: add `#![feature(adt_const_params)]`
//~| HELP: add `#![feature(adt_const_params)]`
// Needs the feature but can be used, so suggest adding the feature.
fn owo_0<const N: &'static u32>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
// Can only be used in const generics with changes.
struct Meow {
@ -18,22 +23,17 @@ struct Meow {
fn meow_0<const N: Meow>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_1<const N: &'static Meow>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_2<const N: [Meow; 100]>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_3<const N: (Meow, u8)>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
// This is suboptimal that it thinks it can be used
// but better to suggest the feature to the user.
fn meow_4<const N: (Meow, String)>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
// Non-local ADT that does not impl `ConstParamTy`
fn nya_0<const N: String>() {}

View File

@ -7,58 +7,76 @@ LL | fn uwu_0<const N: &'static mut ()>() {}
= note: the only supported types are integers, `bool` and `char`
error: `&'static u32` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:10:19
--> $DIR/suggest_feature_only_when_possible.rs:16:19
|
LL | fn owo_0<const N: &'static u32>() {}
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `Meow` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:19:20
--> $DIR/suggest_feature_only_when_possible.rs:24:20
|
LL | fn meow_0<const N: Meow>() {}
| ^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&'static Meow` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:22:20
--> $DIR/suggest_feature_only_when_possible.rs:26:20
|
LL | fn meow_1<const N: &'static Meow>() {}
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `[Meow; 100]` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:25:20
--> $DIR/suggest_feature_only_when_possible.rs:28:20
|
LL | fn meow_2<const N: [Meow; 100]>() {}
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `(Meow, u8)` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:28:20
--> $DIR/suggest_feature_only_when_possible.rs:30:20
|
LL | fn meow_3<const N: (Meow, u8)>() {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `(Meow, String)` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:34:20
--> $DIR/suggest_feature_only_when_possible.rs:35:20
|
LL | fn meow_4<const N: (Meow, String)>() {}
| ^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `String` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:39:19

View File

@ -35,7 +35,10 @@ LL | struct A<const N: &u8>;
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:14:15
@ -44,7 +47,10 @@ LL | impl<const N: &u8> A<N> {
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:22:15
@ -53,7 +59,10 @@ LL | impl<const N: &u8> B for A<N> {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:26:17
@ -62,7 +71,10 @@ LL | fn bar<const N: &u8>() {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:17:21
@ -71,7 +83,10 @@ LL | fn foo<const M: &u8>(&self) {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 10 previous errors

View File

@ -21,7 +21,10 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `[u8; N]` is forbidden as the type of a const generic parameter
--> $DIR/const-param-type-depends-on-const-param.rs:15:35
@ -30,7 +33,10 @@ LL | pub struct SelfDependent<const N: [u8; N]>;
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 4 previous errors

View File

@ -23,7 +23,10 @@ LL | struct B<const CFG: Config> {
| ^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 3 previous errors

View File

@ -54,7 +54,10 @@ note: impl defined here, but it is not `const`
LL | impl const std::ops::Add for Foo {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(effects)]` to the crate attributes to enable
help: add `#![feature(effects)]` to the crate attributes to enable
|
LL + #![feature(effects)]
|
error[E0015]: cannot call non-const fn `<Foo as Add>::add` in constants
--> $DIR/unify-op-with-fn-call.rs:21:13
@ -63,7 +66,10 @@ LL | bar::<{ std::ops::Add::add(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(effects)]` to the crate attributes to enable
help: add `#![feature(effects)]` to the crate attributes to enable
|
LL + #![feature(effects)]
|
error[E0015]: cannot call non-const fn `<usize as Add>::add` in constants
--> $DIR/unify-op-with-fn-call.rs:30:14
@ -72,7 +78,10 @@ LL | bar2::<{ std::ops::Add::add(N, N) }>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(effects)]` to the crate attributes to enable
help: add `#![feature(effects)]` to the crate attributes to enable
|
LL + #![feature(effects)]
|
error: aborting due to 7 previous errors

View File

@ -14,7 +14,10 @@ LL | trait Trait<const S: &'static str> {}
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -6,7 +6,10 @@ LL | (||1usize)()
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 1 previous error

View File

@ -13,7 +13,10 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -13,7 +13,10 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error[E0747]: type provided when a constant was expected
--> $DIR/issue-62878.rs:10:11
@ -22,7 +25,10 @@ LL | foo::<_, { [1] }>();
| ^
|
= help: const arguments cannot yet be inferred with `_`
= help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
|
LL + #![feature(generic_arg_infer)]
|
error: aborting due to 3 previous errors

View File

@ -5,7 +5,10 @@ LL | fn test<const T: &'static dyn A>() {
| ^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -8,7 +8,10 @@ LL | <u8 as Baz>::Quaks: Bar,
[u16; 4]
[[u16; 3]; 3]
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
|
LL + #![feature(trivial_bounds)]
|
error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
--> $DIR/issue-67185-2.rs:14:5
@ -20,7 +23,10 @@ LL | [<u8 as Baz>::Quaks; 2]: Bar,
[u16; 4]
[[u16; 3]; 3]
= help: see issue #48214
= help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
|
LL + #![feature(trivial_bounds)]
|
error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
--> $DIR/issue-67185-2.rs:21:6

View File

@ -5,7 +5,10 @@ LL | struct Collatz<const N: Option<usize>>;
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:12:7

View File

@ -14,7 +14,10 @@ LL | struct Collatz<const N: Option<usize>>;
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:12:7

View File

@ -5,7 +5,10 @@ LL | struct Const<const V: [usize; 0]> {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -5,7 +5,10 @@ LL | struct Foo<const V: [usize; 0] > {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -13,7 +13,10 @@ LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
| ^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -5,7 +5,10 @@ LL | fn hoge<const IN: [u32; LEN]>() {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -5,7 +5,10 @@ LL | fn a<const X: &'static [u32]>() {}
| ^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -5,7 +5,10 @@ LL | fn test<const N: [u8; 1 + 2]>() {}
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter
--> $DIR/issue-74101.rs:9:21
@ -14,7 +17,10 @@ LL | struct Foo<const N: [u8; 1 + 2]>;
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -5,7 +5,10 @@ LL | fn ice_struct_fn<const I: IceEnum>() {}
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -5,7 +5,10 @@ LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:19:23
@ -14,8 +17,11 @@ LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:19:23
@ -24,8 +30,11 @@ LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:19:23
@ -34,8 +43,11 @@ LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 4 previous errors

View File

@ -5,7 +5,10 @@ LL | struct Foo<const N: [u8; Bar::<u32>::value()]>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -29,7 +29,10 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:22:10
@ -40,7 +43,10 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 4 previous errors

View File

@ -11,7 +11,10 @@ LL | struct S<'a, const N: S2>(&'a ());
| ^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -5,7 +5,10 @@ LL | struct Foo<const N: [u8; 0]>;
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `()` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:6:21
@ -14,7 +17,10 @@ LL | struct Bar<const N: ()>;
| ^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `No` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:11:21
@ -23,7 +29,10 @@ LL | struct Fez<const N: No>;
| ^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:14:21
@ -32,7 +41,10 @@ LL | struct Faz<const N: &'static u8>;
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `!` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:17:21
@ -49,7 +61,10 @@ LL | enum Goo<const N: ()> { A, B }
| ^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `()` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:23:20
@ -58,7 +73,10 @@ LL | union Boo<const N: ()> { a: () }
| ^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 7 previous errors

View File

@ -30,7 +30,10 @@ LL | | }]>;
| |__^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -5,7 +5,10 @@ LL | struct ConstString<const T: &'static str>;
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&'static [u8]` is forbidden as the type of a const generic parameter
--> $DIR/slice-const-param-mismatch.rs:9:28
@ -14,7 +17,10 @@ LL | struct ConstBytes<const T: &'static [u8]>;
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error[E0308]: mismatched types
--> $DIR/slice-const-param-mismatch.rs:14:35

View File

@ -5,7 +5,10 @@ LL | struct _Range<const R: std::ops::Range<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
@ -14,7 +17,10 @@ LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `RangeFull` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:18:28
@ -23,7 +29,10 @@ LL | struct _RangeFull<const R: std::ops::RangeFull>;
| ^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
@ -32,7 +41,10 @@ LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `RangeTo<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:29:26
@ -41,7 +53,10 @@ LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:34:35
@ -50,7 +65,10 @@ LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 6 previous errors

View File

@ -5,7 +5,10 @@ LL | struct Const<const P: &'static ()>;
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 1 previous error

View File

@ -5,7 +5,10 @@ LL | trait Get<'a, const N: &'static str> {
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: `&'static str` is forbidden as the type of a const generic parameter
--> $DIR/issue-71348.rs:18:25
@ -14,7 +17,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
error: aborting due to 2 previous errors

View File

@ -23,7 +23,10 @@ LL | for i in 0..x {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/const-fn-error.rs:5:14
@ -42,7 +45,10 @@ LL | for i in 0..x {
| ^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 4 previous errors

View File

@ -17,7 +17,10 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0658]: mutable references are not allowed in constants
--> $DIR/const-for-feature-gate.rs:4:14
@ -36,7 +39,10 @@ LL | for _ in 0..5 {}
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 4 previous errors

View File

@ -7,7 +7,10 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/const-for.rs:5:14
@ -16,7 +19,10 @@ LL | for _ in 0..5 {}
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 2 previous errors

View File

@ -17,7 +17,10 @@ LL | Some(())?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
--> $DIR/const-try-feature-gate.rs:4:5
@ -28,7 +31,10 @@ LL | Some(())?;
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/option.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
LL + #![feature(const_trait_impl)]
|
error: aborting due to 3 previous errors

View File

@ -10,7 +10,10 @@ note: impl defined here, but it is not `const`
LL | impl const Try for TryMe {
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(effects)]` to the crate attributes to enable
help: add `#![feature(effects)]` to the crate attributes to enable
|
LL + #![feature(effects)]
|
error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
--> $DIR/const-try.rs:33:5
@ -24,7 +27,10 @@ note: impl defined here, but it is not `const`
LL | impl const FromResidual<Error> for TryMe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: add `#![feature(effects)]` to the crate attributes to enable
help: add `#![feature(effects)]` to the crate attributes to enable
|
LL + #![feature(effects)]
|
error: aborting due to 2 previous errors

Some files were not shown because too many files have changed in this diff Show More