Auto merge of #143407 - jhpratt:rollup-ekkoubw, r=jhpratt
Rollup of 11 pull requests Successful merges: - rust-lang/rust#142749 (Add methods for converting bool to `Result<(), E>`) - rust-lang/rust#143288 (Fix `x clean` with a fifo) - rust-lang/rust#143307 (Fast path nitpicks) - rust-lang/rust#143346 (update coherence example) - rust-lang/rust#143356 (use unsigned_abs instead of `abs` on signed int to silence clippy) - rust-lang/rust#143370 (remove redundant #[must_use]) - rust-lang/rust#143378 (simplify receivers for some array method calls) - rust-lang/rust#143380 (Replace kw_span by full span for generic const parameters.) - rust-lang/rust#143381 (rustdoc: don't treat methods under const impls or traits as const) - rust-lang/rust#143394 (compiler: Document and reduce `fn provide`s in hir crates) - rust-lang/rust#143395 (Always use the pure Rust fallback instead of `llvm.{maximum,minimum}`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c96a69059e
43 changed files with 247 additions and 125 deletions
|
|
@ -385,8 +385,8 @@ pub enum GenericParamKind {
|
|||
},
|
||||
Const {
|
||||
ty: P<Ty>,
|
||||
/// Span of the `const` keyword.
|
||||
kw_span: Span,
|
||||
/// Span of the whole parameter definition, including default.
|
||||
span: Span,
|
||||
/// Optional default value for the const generic param.
|
||||
default: Option<AnonConst>,
|
||||
},
|
||||
|
|
@ -410,10 +410,7 @@ impl GenericParam {
|
|||
self.ident.span
|
||||
}
|
||||
GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),
|
||||
GenericParamKind::Const { kw_span, default: Some(default), .. } => {
|
||||
kw_span.to(default.value.span)
|
||||
}
|
||||
GenericParamKind::Const { kw_span, default: None, ty } => kw_span.to(ty.span),
|
||||
GenericParamKind::Const { span, .. } => *span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1350,9 +1350,10 @@ macro_rules! common_visitor_and_walkers {
|
|||
match kind {
|
||||
GenericParamKind::Lifetime => (),
|
||||
GenericParamKind::Type { default } => visit_opt!(vis, visit_ty, default),
|
||||
GenericParamKind::Const { ty, default, kw_span: _ } => {
|
||||
GenericParamKind::Const { ty, default, span } => {
|
||||
try_visit!(vis.visit_ty(ty));
|
||||
visit_opt!(vis, visit_anon_const, default);
|
||||
try_visit!(visit_span(vis, span));
|
||||
}
|
||||
}
|
||||
if let Some(sp) = colon_span {
|
||||
|
|
|
|||
|
|
@ -1960,7 +1960,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
|
||||
}
|
||||
GenericParamKind::Const { ty, kw_span: _, default } => {
|
||||
GenericParamKind::Const { ty, span: _, default } => {
|
||||
let ty = self
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
|
||||
|
||||
|
|
|
|||
|
|
@ -909,11 +909,11 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
|
|||
}
|
||||
GenericParamKind::Type { default: None } => (),
|
||||
GenericParamKind::Lifetime => (),
|
||||
GenericParamKind::Const { ty: _, kw_span: _, default: Some(default) } => {
|
||||
GenericParamKind::Const { ty: _, span: _, default: Some(default) } => {
|
||||
ordered_params += " = ";
|
||||
ordered_params += &pprust::expr_to_string(&default.value);
|
||||
}
|
||||
GenericParamKind::Const { ty: _, kw_span: _, default: None } => (),
|
||||
GenericParamKind::Const { ty: _, span: _, default: None } => (),
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
|||
GenericParamKind::Type { default: _ } => {
|
||||
cx.typaram(p.span(), p.ident, p.bounds.clone(), None)
|
||||
}
|
||||
GenericParamKind::Const { ty, kw_span: _, default: _ } => cx
|
||||
GenericParamKind::Const { ty, span: _, default: _ } => cx
|
||||
.const_param(
|
||||
p.span(),
|
||||
p.ident,
|
||||
|
|
|
|||
|
|
@ -664,10 +664,10 @@ impl<'a> TraitDef<'a> {
|
|||
|
||||
cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
|
||||
}
|
||||
GenericParamKind::Const { ty, kw_span, .. } => {
|
||||
GenericParamKind::Const { ty, span, .. } => {
|
||||
let const_nodefault_kind = GenericParamKind::Const {
|
||||
ty: ty.clone(),
|
||||
kw_span: kw_span.with_ctxt(ctxt),
|
||||
span: span.with_ctxt(ctxt),
|
||||
|
||||
// We can't have default values inside impl block
|
||||
default: None,
|
||||
|
|
|
|||
|
|
@ -103,23 +103,25 @@ fn call_simple_intrinsic<'ll, 'tcx>(
|
|||
sym::minnumf64 => ("llvm.minnum", &[bx.type_f64()]),
|
||||
sym::minnumf128 => ("llvm.minnum", &[bx.type_f128()]),
|
||||
|
||||
sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
|
||||
sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
|
||||
sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]),
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant,
|
||||
// let's instead use the intrinsic fallback body.
|
||||
// sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]),
|
||||
// FIXME: LLVM currently mis-compile those intrinsics, re-enable them
|
||||
// when llvm/llvm-project#{139380,139381,140445} are fixed.
|
||||
//sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
|
||||
//sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
|
||||
//sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]),
|
||||
//sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]),
|
||||
//
|
||||
sym::maxnumf16 => ("llvm.maxnum", &[bx.type_f16()]),
|
||||
sym::maxnumf32 => ("llvm.maxnum", &[bx.type_f32()]),
|
||||
sym::maxnumf64 => ("llvm.maxnum", &[bx.type_f64()]),
|
||||
sym::maxnumf128 => ("llvm.maxnum", &[bx.type_f128()]),
|
||||
|
||||
sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
|
||||
sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
|
||||
sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]),
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant,
|
||||
// let's instead use the intrinsic fallback body.
|
||||
// sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]),
|
||||
// FIXME: LLVM currently mis-compile those intrinsics, re-enable them
|
||||
// when llvm/llvm-project#{139380,139381,140445} are fixed.
|
||||
//sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
|
||||
//sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
|
||||
//sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]),
|
||||
//sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]),
|
||||
//
|
||||
sym::copysignf16 => ("llvm.copysign", &[bx.type_f16()]),
|
||||
sym::copysignf32 => ("llvm.copysign", &[bx.type_f32()]),
|
||||
sym::copysignf64 => ("llvm.copysign", &[bx.type_f64()]),
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
attrs: AttrVec::new(),
|
||||
bounds,
|
||||
is_placeholder: false,
|
||||
kind: ast::GenericParamKind::Const { ty, kw_span: DUMMY_SP, default },
|
||||
kind: ast::GenericParamKind::Const { ty, span: DUMMY_SP, default },
|
||||
colon_span: None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
|
|||
use self::region::region_scope_tree;
|
||||
use crate::{errors, require_c_abi_if_c_variadic};
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
wfcheck::provide(providers);
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub(super) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
adt_destructor,
|
||||
adt_async_destructor,
|
||||
|
|
@ -109,6 +109,8 @@ pub fn provide(providers: &mut Providers) {
|
|||
collect_return_position_impl_trait_in_trait_tys,
|
||||
compare_impl_item: compare_impl_item::compare_impl_item,
|
||||
check_coroutine_obligations: check::check_coroutine_obligations,
|
||||
check_type_wf: wfcheck::check_type_wf,
|
||||
check_well_formed: wfcheck::check_well_formed,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};
|
|||
use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
|
||||
use rustc_macros::LintDiagnostic;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::solve::NoSolution;
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
|
|
@ -189,7 +188,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
pub(super) fn check_well_formed(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let mut res = crate::check::check::check_item_type(tcx, def_id);
|
||||
|
||||
for param in &tcx.generics_of(def_id).own_params {
|
||||
|
|
@ -2249,7 +2251,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
|
||||
pub(super) fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
|
||||
let items = tcx.hir_crate_items(());
|
||||
let res = items
|
||||
.par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))
|
||||
|
|
@ -2397,7 +2399,3 @@ struct RedundantLifetimeArgsLint<'tcx> {
|
|||
// The lifetime we can replace the victim with.
|
||||
candidate: ty::Region<'tcx>,
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { check_type_wf, check_well_formed, ..*providers };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint;
|
||||
use tracing::debug;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { check_unused_traits, ..*providers };
|
||||
}
|
||||
|
||||
fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
|
||||
pub(super) fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
|
||||
let mut used_trait_imports = UnordSet::<LocalDefId>::default();
|
||||
|
||||
// FIXME: Use `tcx.hir_par_body_owners()` when we implement creating `DefId`s
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ fn enforce_empty_impls_for_marker_traits(
|
|||
.emit())
|
||||
}
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`].
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
use self::builtin::coerce_unsized_info;
|
||||
use self::inherent_impls::{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ mod type_of;
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
resolve_bound_vars::provide(providers);
|
||||
*providers = Providers {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ enum BinderScopeType {
|
|||
|
||||
type ScopeRef<'a> = &'a Scope<'a>;
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
resolve_bound_vars,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind};
|
|||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
|
@ -12,13 +11,9 @@ use tracing::debug;
|
|||
|
||||
use crate::collect::ItemCtxt;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
|
||||
}
|
||||
|
||||
// Ideally, this would be in `rustc_trait_selection`, but we
|
||||
// need access to `ItemCtxt`
|
||||
fn diagnostic_hir_wf_check<'tcx>(
|
||||
pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
|
||||
) -> Option<ObligationCause<'tcx>> {
|
||||
|
|
|
|||
|
|
@ -150,18 +150,21 @@ fn require_c_abi_if_c_variadic(
|
|||
.emit();
|
||||
}
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
collect::provide(providers);
|
||||
coherence::provide(providers);
|
||||
check::provide(providers);
|
||||
check_unused::provide(providers);
|
||||
variance::provide(providers);
|
||||
outlives::provide(providers);
|
||||
hir_wf_check::provide(providers);
|
||||
*providers = Providers {
|
||||
check_unused_traits: check_unused::check_unused_traits,
|
||||
diagnostic_hir_wf_check: hir_wf_check::diagnostic_hir_wf_check,
|
||||
inferred_outlives_crate: outlives::inferred_outlives_crate,
|
||||
inferred_outlives_of: outlives::inferred_outlives_of,
|
||||
inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
|
||||
enforce_impl_non_lifetime_params_are_constrained:
|
||||
impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
|
||||
crate_variances: variance::crate_variances,
|
||||
variances_of: variance::variances_of,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, CratePredicatesMap, GenericArgKind, TyCtxt, Upcast};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
@ -9,11 +8,10 @@ mod explicit;
|
|||
mod implicit_infer;
|
||||
mod utils;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
|
||||
}
|
||||
|
||||
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
|
||||
pub(super) fn inferred_outlives_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
item_def_id: LocalDefId,
|
||||
) -> &[(ty::Clause<'_>, Span)] {
|
||||
match tcx.def_kind(item_def_id) {
|
||||
DefKind::Struct | DefKind::Enum | DefKind::Union => {
|
||||
let crate_map = tcx.inferred_outlives_crate(());
|
||||
|
|
@ -48,7 +46,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
|
|||
}
|
||||
}
|
||||
|
||||
fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
|
||||
pub(super) fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
|
||||
// Compute a map from each ADT (struct/enum/union) and lazy type alias to
|
||||
// the **explicit** outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
|
||||
// Typically there won't be many of these, except in older code where
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use rustc_arena::DroplessArena;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{
|
||||
self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
|
|
@ -27,18 +26,14 @@ mod solve;
|
|||
|
||||
pub(crate) mod dump;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { variances_of, crate_variances, ..*providers };
|
||||
}
|
||||
|
||||
fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
|
||||
pub(super) fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
|
||||
let arena = DroplessArena::default();
|
||||
let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &arena);
|
||||
let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
|
||||
solve::solve_constraints(constraints_cx)
|
||||
}
|
||||
|
||||
fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
|
||||
pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
|
||||
// Skip items with no generics - there's nothing to infer in them.
|
||||
if tcx.generics_of(item_def_id).is_empty() {
|
||||
return &[];
|
||||
|
|
|
|||
|
|
@ -536,7 +536,12 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
|
|||
diag.emit()
|
||||
}
|
||||
|
||||
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
method::provide(providers);
|
||||
*providers = Providers { typeck, used_trait_imports, ..*providers };
|
||||
*providers = Providers {
|
||||
method_autoderef_steps: method::probe::method_autoderef_steps,
|
||||
typeck,
|
||||
used_trait_imports,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, InferOk};
|
||||
use rustc_infer::traits::PredicateObligations;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt,
|
||||
|
|
@ -28,10 +27,6 @@ pub(crate) use self::MethodError::*;
|
|||
use self::probe::{IsSuggestion, ProbeScope};
|
||||
use crate::FnCtxt;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
probe::provide(providers);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) struct MethodCallee<'tcx> {
|
||||
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons
|
|||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::elaborate::supertrait_def_ids;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
|
||||
use rustc_middle::ty::{
|
||||
|
|
@ -554,11 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
providers.method_autoderef_steps = method_autoderef_steps;
|
||||
}
|
||||
|
||||
fn method_autoderef_steps<'tcx>(
|
||||
pub(crate) fn method_autoderef_steps<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
goal: CanonicalTyGoal<'tcx>,
|
||||
) -> MethodAutoderefStepsResult<'tcx> {
|
||||
|
|
|
|||
|
|
@ -114,13 +114,18 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Parse optional const generics default value.
|
||||
let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
|
||||
let span = if let Some(ref default) = default {
|
||||
const_span.to(default.value.span)
|
||||
} else {
|
||||
const_span.to(ty.span)
|
||||
};
|
||||
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: preceding_attrs,
|
||||
bounds: Vec::new(),
|
||||
kind: GenericParamKind::Const { ty, kw_span: const_span, default },
|
||||
kind: GenericParamKind::Const { ty, span, default },
|
||||
is_placeholder: false,
|
||||
colon_span: None,
|
||||
})
|
||||
|
|
@ -137,6 +142,11 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Parse optional const generics default value.
|
||||
let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
|
||||
let span = if let Some(ref default) = default {
|
||||
mistyped_const_ident.span.to(default.value.span)
|
||||
} else {
|
||||
mistyped_const_ident.span.to(ty.span)
|
||||
};
|
||||
|
||||
self.dcx()
|
||||
.struct_span_err(
|
||||
|
|
@ -156,7 +166,7 @@ impl<'a> Parser<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: preceding_attrs,
|
||||
bounds: Vec::new(),
|
||||
kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default },
|
||||
kind: GenericParamKind::Const { ty, span, default },
|
||||
is_placeholder: false,
|
||||
colon_span: None,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1656,7 +1656,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
forward_ty_ban_rib.bindings.swap_remove(i);
|
||||
forward_ty_ban_rib_const_param_ty.bindings.swap_remove(i);
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
|
||||
GenericParamKind::Const { ref ty, span: _, ref default } => {
|
||||
// Const parameters can't have param bounds.
|
||||
assert!(param.bounds.is_empty());
|
||||
|
||||
|
|
|
|||
|
|
@ -2940,7 +2940,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
let span = if let [.., bound] = ¶m.bounds[..] {
|
||||
bound.span()
|
||||
} else if let GenericParam {
|
||||
kind: GenericParamKind::Const { ty, kw_span: _, default }, ..
|
||||
kind: GenericParamKind::Const { ty, span: _, default }, ..
|
||||
} = param {
|
||||
default.as_ref().map(|def| def.value.span).unwrap_or(ty.span)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -21,19 +21,9 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
|
|||
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) =
|
||||
key.value.predicate.kind().skip_binder()
|
||||
&& term.is_trivially_wf(tcx)
|
||||
{
|
||||
match term.as_type()?.kind() {
|
||||
ty::Param(_)
|
||||
| ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Uint(_) => {
|
||||
return Some(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return Some(());
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
|||
|
|
@ -368,16 +368,17 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
|||
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
|
||||
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
|
||||
// canonicalize and all that for such cases.
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
|
||||
predicate.kind().skip_binder()
|
||||
&& trait_pred.polarity == ty::PredicatePolarity::Positive
|
||||
{
|
||||
let sizedness = match tcx.as_lang_item(trait_ref.def_id()) {
|
||||
let sizedness = match tcx.as_lang_item(trait_pred.def_id()) {
|
||||
Some(LangItem::Sized) => SizedTraitKind::Sized,
|
||||
Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
if trait_ref.self_ty().has_trivial_sizedness(tcx, sizedness) {
|
||||
if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
|
||||
debug!("fast path -- trivial sizedness");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::CodegenObligationError;
|
||||
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast};
|
||||
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
|
||||
SelectionError, sizedness_fast_path,
|
||||
SelectionError,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -34,13 +34,6 @@ pub(crate) fn codegen_select_candidate<'tcx>(
|
|||
let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
|
||||
if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) {
|
||||
return Ok(&*tcx.arena.alloc(ImplSource::Builtin(
|
||||
ty::solve::BuiltinImplSource::Trivial,
|
||||
Default::default(),
|
||||
)));
|
||||
}
|
||||
|
||||
let obligation_cause = ObligationCause::dummy();
|
||||
let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
|
||||
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ impl<T, const N: usize> [T; N] {
|
|||
)]
|
||||
#[inline]
|
||||
pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
|
||||
(&self[..]).split_first_chunk::<M>().unwrap()
|
||||
self.split_first_chunk::<M>().unwrap()
|
||||
}
|
||||
|
||||
/// Divides one mutable array reference into two at an index.
|
||||
|
|
@ -740,7 +740,7 @@ impl<T, const N: usize> [T; N] {
|
|||
)]
|
||||
#[inline]
|
||||
pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
|
||||
(&mut self[..]).split_first_chunk_mut::<M>().unwrap()
|
||||
self.split_first_chunk_mut::<M>().unwrap()
|
||||
}
|
||||
|
||||
/// Divides one array reference into two at an index from the end.
|
||||
|
|
@ -785,7 +785,7 @@ impl<T, const N: usize> [T; N] {
|
|||
)]
|
||||
#[inline]
|
||||
pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
|
||||
(&self[..]).split_last_chunk::<M>().unwrap()
|
||||
self.split_last_chunk::<M>().unwrap()
|
||||
}
|
||||
|
||||
/// Divides one mutable array reference into two at an index from the end.
|
||||
|
|
@ -818,7 +818,7 @@ impl<T, const N: usize> [T; N] {
|
|||
)]
|
||||
#[inline]
|
||||
pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
|
||||
(&mut self[..]).split_last_chunk_mut::<M>().unwrap()
|
||||
self.split_last_chunk_mut::<M>().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,4 +61,71 @@ impl bool {
|
|||
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
if self { Some(f()) } else { None }
|
||||
}
|
||||
|
||||
/// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html),
|
||||
/// or `Err(err)` otherwise.
|
||||
///
|
||||
/// Arguments passed to `ok_or` are eagerly evaluated; if you are
|
||||
/// passing the result of a function call, it is recommended to use
|
||||
/// [`ok_or_else`], which is lazily evaluated.
|
||||
///
|
||||
/// [`ok_or_else`]: bool::ok_or_else
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_result)]
|
||||
///
|
||||
/// assert_eq!(false.ok_or(0), Err(0));
|
||||
/// assert_eq!(true.ok_or(0), Ok(()));
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_result)]
|
||||
///
|
||||
/// let mut a = 0;
|
||||
/// let mut function_with_side_effects = || { a += 1; };
|
||||
///
|
||||
/// assert!(true.ok_or(function_with_side_effects()).is_ok());
|
||||
/// assert!(false.ok_or(function_with_side_effects()).is_err());
|
||||
///
|
||||
/// // `a` is incremented twice because the value passed to `ok_or` is
|
||||
/// // evaluated eagerly.
|
||||
/// assert_eq!(a, 2);
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_result", issue = "142748")]
|
||||
#[inline]
|
||||
pub fn ok_or<E>(self, err: E) -> Result<(), E> {
|
||||
if self { Ok(()) } else { Err(err) }
|
||||
}
|
||||
|
||||
/// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html),
|
||||
/// or `Err(f())` otherwise.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_result)]
|
||||
///
|
||||
/// assert_eq!(false.ok_or_else(|| 0), Err(0));
|
||||
/// assert_eq!(true.ok_or_else(|| 0), Ok(()));
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_result)]
|
||||
///
|
||||
/// let mut a = 0;
|
||||
///
|
||||
/// assert!(true.ok_or_else(|| { a += 1; }).is_ok());
|
||||
/// assert!(false.ok_or_else(|| { a += 1; }).is_err());
|
||||
///
|
||||
/// // `a` is incremented once because the closure is evaluated lazily by
|
||||
/// // `ok_or_else`.
|
||||
/// assert_eq!(a, 1);
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_result", issue = "142748")]
|
||||
#[inline]
|
||||
pub fn ok_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(), E> {
|
||||
if self { Ok(()) } else { Err(f()) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1449,7 +1449,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
|
|||
/// check `==` and `<` separately to do rather than needing to calculate
|
||||
/// (then optimize out) the three-way `Ordering` result.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
// Added to improve the behaviour of tuples; not necessarily stabilization-track.
|
||||
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
|
|
@ -1459,7 +1458,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
|
|||
|
||||
/// Same as `__chaining_lt`, but for `<=` instead of `<`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> {
|
||||
|
|
@ -1468,7 +1466,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
|
|||
|
||||
/// Same as `__chaining_lt`, but for `>` instead of `<`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> {
|
||||
|
|
@ -1477,7 +1474,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
|
|||
|
||||
/// Same as `__chaining_lt`, but for `>=` instead of `<`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {
|
||||
|
|
|
|||
|
|
@ -943,7 +943,7 @@ impl f64 {
|
|||
/// This returns NaN when *either* argument is NaN, as opposed to
|
||||
/// [`f64::max`] which only returns NaN when *both* arguments are NaN.
|
||||
///
|
||||
/// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087)
|
||||
/// ```
|
||||
/// #![feature(float_minimum_maximum)]
|
||||
/// let x = 1.0_f64;
|
||||
/// let y = 2.0_f64;
|
||||
|
|
@ -970,7 +970,7 @@ impl f64 {
|
|||
/// This returns NaN when *either* argument is NaN, as opposed to
|
||||
/// [`f64::min`] which only returns NaN when *both* arguments are NaN.
|
||||
///
|
||||
/// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087)
|
||||
/// ```
|
||||
/// #![feature(float_minimum_maximum)]
|
||||
/// let x = 1.0_f64;
|
||||
/// let y = 2.0_f64;
|
||||
|
|
|
|||
|
|
@ -2572,7 +2572,7 @@ macro_rules! uint_impl {
|
|||
if size_of::<Self>() == 1 {
|
||||
// Trick LLVM into generating the psadbw instruction when SSE2
|
||||
// is available and this function is autovectorized for u8's.
|
||||
(self as i32).wrapping_sub(other as i32).abs() as Self
|
||||
(self as i32).wrapping_sub(other as i32).unsigned_abs() as Self
|
||||
} else {
|
||||
if self < other {
|
||||
other - self
|
||||
|
|
|
|||
|
|
@ -105,3 +105,11 @@ fn test_bool_to_option() {
|
|||
assert_eq!(D, Some(0));
|
||||
*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_to_result() {
|
||||
assert_eq!(false.ok_or(0), Err(0));
|
||||
assert_eq!(true.ok_or(0), Ok(()));
|
||||
assert_eq!(false.ok_or_else(|| 0), Err(0));
|
||||
assert_eq!(true.ok_or_else(|| 0), Ok(()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#![feature(async_iter_from_iter)]
|
||||
#![feature(async_iterator)]
|
||||
#![feature(bigint_helper_methods)]
|
||||
#![feature(bool_to_result)]
|
||||
#![feature(bstr)]
|
||||
#![feature(cfg_target_has_reliable_f16_f128)]
|
||||
#![feature(char_max_len)]
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ fn rm_rf(path: &Path) {
|
|||
panic!("failed to get metadata for file {}: {}", path.display(), e);
|
||||
}
|
||||
Ok(metadata) => {
|
||||
if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
|
||||
if !metadata.file_type().is_dir() {
|
||||
do_op(path, "remove file", |p| match fs::remove_file(p) {
|
||||
#[cfg(windows)]
|
||||
Err(e)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ Finally, we check whether the item bounds of the opaque hold for the expected ty
|
|||
[source][item-bounds-ck].
|
||||
|
||||
[norm]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L13
|
||||
[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
|
||||
[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs
|
||||
[placeholder-ck]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L33
|
||||
[check-storage]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L52
|
||||
[eq-prev]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L59
|
||||
|
|
|
|||
|
|
@ -647,7 +647,20 @@ impl Item {
|
|||
) -> hir::FnHeader {
|
||||
let sig = tcx.fn_sig(def_id).skip_binder();
|
||||
let constness = if tcx.is_const_fn(def_id) {
|
||||
hir::Constness::Const
|
||||
// rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent
|
||||
// or that have a `#[const_trait]` parent. Do not display those as `const` in rustdoc because we
|
||||
// won't be printing correct syntax plus the syntax is unstable.
|
||||
match tcx.opt_associated_item(def_id) {
|
||||
Some(ty::AssocItem {
|
||||
container: ty::AssocItemContainer::Impl,
|
||||
trait_item_def_id: Some(_),
|
||||
..
|
||||
})
|
||||
| Some(ty::AssocItem { container: ty::AssocItemContainer::Trait, .. }) => {
|
||||
hir::Constness::NotConst
|
||||
}
|
||||
None | Some(_) => hir::Constness::Const,
|
||||
}
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
};
|
||||
|
|
|
|||
|
|
@ -886,13 +886,13 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool {
|
|||
(
|
||||
Const {
|
||||
ty: lt,
|
||||
kw_span: _,
|
||||
default: ld,
|
||||
span: _,
|
||||
},
|
||||
Const {
|
||||
ty: rt,
|
||||
kw_span: _,
|
||||
default: rd,
|
||||
span: _,
|
||||
},
|
||||
) => eq_ty(lt, rt) && both(ld.as_ref(), rd.as_ref(), eq_anon_const),
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ impl Spanned for ast::GenericParam {
|
|||
fn span(&self) -> Span {
|
||||
let lo = match self.kind {
|
||||
_ if !self.attrs.is_empty() => self.attrs[0].span.lo(),
|
||||
ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(),
|
||||
ast::GenericParamKind::Const { span, .. } => span.lo(),
|
||||
_ => self.ident.span.lo(),
|
||||
};
|
||||
let hi = if self.bounds.is_empty() {
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ impl Rewrite for ast::GenericParam {
|
|||
|
||||
let param_start = if let ast::GenericParamKind::Const {
|
||||
ref ty,
|
||||
kw_span,
|
||||
span,
|
||||
default,
|
||||
} = &self.kind
|
||||
{
|
||||
|
|
@ -711,7 +711,7 @@ impl Rewrite for ast::GenericParam {
|
|||
default.rewrite_result(context, Shape::legacy(budget, shape.indent))?;
|
||||
param.push_str(&rewrite);
|
||||
}
|
||||
kw_span.lo()
|
||||
span.lo()
|
||||
} else {
|
||||
param.push_str(rewrite_ident(context, self.ident));
|
||||
self.ident.span.lo()
|
||||
|
|
|
|||
36
tests/rustdoc/constant/const-trait-and-impl-methods.rs
Normal file
36
tests/rustdoc/constant/const-trait-and-impl-methods.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// check that we don't render `#[const_trait]` methods as `const` - even for
|
||||
// const `trait`s and `impl`s.
|
||||
#![crate_name = "foo"]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
//@ has foo/trait.Tr.html
|
||||
//@ has - '//*[@id="tymethod.required"]' 'fn required()'
|
||||
//@ !has - '//*[@id="tymethod.required"]' 'const'
|
||||
//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()'
|
||||
//@ !has - '//*[@id="method.defaulted"]' 'const'
|
||||
#[const_trait]
|
||||
pub trait Tr {
|
||||
fn required();
|
||||
fn defaulted() {}
|
||||
}
|
||||
|
||||
pub struct ConstImpl {}
|
||||
pub struct NonConstImpl {}
|
||||
|
||||
//@ has foo/struct.ConstImpl.html
|
||||
//@ has - '//*[@id="method.required"]' 'fn required()'
|
||||
//@ !has - '//*[@id="method.required"]' 'const'
|
||||
//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()'
|
||||
//@ !has - '//*[@id="method.defaulted"]' 'const'
|
||||
impl const Tr for ConstImpl {
|
||||
fn required() {}
|
||||
}
|
||||
|
||||
//@ has foo/struct.NonConstImpl.html
|
||||
//@ has - '//*[@id="method.required"]' 'fn required()'
|
||||
//@ !has - '//*[@id="method.required"]' 'const'
|
||||
//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()'
|
||||
//@ !has - '//*[@id="method.defaulted"]' 'const'
|
||||
impl Tr for NonConstImpl {
|
||||
fn required() {}
|
||||
}
|
||||
8
tests/ui/traits/negative-bounds/negative-sized.rs
Normal file
8
tests/ui/traits/negative-bounds/negative-sized.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#![feature(negative_bounds)]
|
||||
|
||||
fn foo<T: !Sized>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<()>();
|
||||
//~^ ERROR the trait bound `(): !Sized` is not satisfied
|
||||
}
|
||||
15
tests/ui/traits/negative-bounds/negative-sized.stderr
Normal file
15
tests/ui/traits/negative-bounds/negative-sized.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error[E0277]: the trait bound `(): !Sized` is not satisfied
|
||||
--> $DIR/negative-sized.rs:6:11
|
||||
|
|
||||
LL | foo::<()>();
|
||||
| ^^ the trait bound `(): !Sized` is not satisfied
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/negative-sized.rs:3:11
|
||||
|
|
||||
LL | fn foo<T: !Sized>() {}
|
||||
| ^^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue