mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-17 01:13:11 +00:00
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:
commit
3c85e56249
@ -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/)
|
||||
|
@ -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() {
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1078,6 +1078,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
|
||||
feature,
|
||||
GateIssue::Language,
|
||||
lint_from_cli,
|
||||
None,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -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 {
|
||||
|
@ -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)]
|
||||
|
@ -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))
|
||||
|
@ -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]
|
||||
|
@ -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 => "",
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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..))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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`"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 });
|
||||
}
|
||||
|
@ -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))
|
||||
}) {
|
||||
|
@ -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
|
||||
|
@ -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: _,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
});
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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))]
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -1 +0,0 @@
|
||||
riscv32imac-unknown-none-elf.md
|
@ -1 +0,0 @@
|
||||
riscv32imac-unknown-none-elf.md
|
@ -1 +0,0 @@
|
||||
riscv32imac-unknown-none-elf.md
|
@ -1 +0,0 @@
|
||||
riscv32imac-unknown-none-elf.md
|
@ -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(
|
||||
|
@ -1,3 +1 @@
|
||||
#![feature(imported_main)]
|
||||
|
||||
use cargo_miri_test::main;
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(imported_main)]
|
||||
|
||||
pub mod foo {
|
||||
pub fn mymain() {
|
||||
println!("Hello, world!");
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(imported_main)]
|
||||
|
||||
mod foo {
|
||||
pub(crate) fn bar() {}
|
||||
}
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
22
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs
Normal file
22
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs
Normal 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() {}
|
@ -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() {}
|
@ -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
|
||||
|
55
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs
Normal file
55
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs
Normal 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() {}
|
76
tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr
Normal file
76
tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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>() {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user