mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #111089 - Dylan-DPC:rollup-b8oj6du, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #105076 (Refactor core::char::EscapeDefault and co. structures) - #108161 (Add `ConstParamTy` trait) - #108668 (Stabilize debugger_visualizer) - #110512 (Fix elaboration with associated type bounds) - #110895 (Remove `all` in target_thread_local cfg) - #110955 (uplift `clippy::clone_double_ref` as `suspicious_double_ref_op`) - #111048 (Mark`feature(return_position_impl_trait_in_trait)` and`feature(async_fn_in_trait)` as not incomplete) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7b99493492
@ -40,7 +40,6 @@ use regex::Regex;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::OnceCell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::ffi::OsString;
|
||||
@ -576,17 +575,17 @@ fn link_dwarf_object<'a>(
|
||||
|
||||
impl<Relocations> ThorinSession<Relocations> {
|
||||
fn alloc_mmap(&self, data: Mmap) -> &Mmap {
|
||||
(*self.arena_mmap.alloc(data)).borrow()
|
||||
&*self.arena_mmap.alloc(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Relocations> thorin::Session<Relocations> for ThorinSession<Relocations> {
|
||||
fn alloc_data(&self, data: Vec<u8>) -> &[u8] {
|
||||
(*self.arena_data.alloc(data)).borrow()
|
||||
&*self.arena_data.alloc(data)
|
||||
}
|
||||
|
||||
fn alloc_relocation(&self, data: Relocations) -> &Relocations {
|
||||
(*self.arena_relocations.alloc(data)).borrow()
|
||||
&*self.arena_relocations.alloc(data)
|
||||
}
|
||||
|
||||
fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
|
||||
|
@ -130,6 +130,8 @@ declare_features! (
|
||||
(accepted, copy_closures, "1.26.0", Some(44490), None),
|
||||
/// Allows `crate` in paths.
|
||||
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
|
||||
/// Allows using `#[debugger_visualizer]` attribute.
|
||||
(accepted, debugger_visualizer, "CURRENT_RUSTC_VERSION", Some(95939), None),
|
||||
/// Allows rustc to inject a default alloc_error_handler
|
||||
(accepted, default_alloc_error_handler, "1.68.0", Some(66741), None),
|
||||
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
|
||||
|
@ -310,7 +310,7 @@ declare_features! (
|
||||
/// Allows `async || body` closures.
|
||||
(active, async_closure, "1.37.0", Some(62290), None),
|
||||
/// Allows async functions to be declared, implemented, and used in traits.
|
||||
(incomplete, async_fn_in_trait, "1.66.0", Some(91611), None),
|
||||
(active, async_fn_in_trait, "1.66.0", Some(91611), None),
|
||||
/// Treat `extern "C"` function as nounwind.
|
||||
(active, c_unwind, "1.52.0", Some(74990), None),
|
||||
/// Allows using C-variadics.
|
||||
@ -363,8 +363,6 @@ declare_features! (
|
||||
(active, custom_inner_attributes, "1.30.0", Some(54726), None),
|
||||
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
|
||||
(active, custom_test_frameworks, "1.30.0", Some(50297), None),
|
||||
/// Allows using `#[debugger_visualizer]`.
|
||||
(active, debugger_visualizer, "1.62.0", Some(95939), None),
|
||||
/// Allows declarative macros 2.0 (`macro`).
|
||||
(active, decl_macro, "1.17.0", Some(39412), None),
|
||||
/// Allows default type parameters to influence type inference.
|
||||
@ -496,7 +494,7 @@ declare_features! (
|
||||
/// Allows `repr(simd)` and importing the various simd intrinsics.
|
||||
(active, repr_simd, "1.4.0", Some(27731), None),
|
||||
/// Allows return-position `impl Trait` in traits.
|
||||
(incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None),
|
||||
(active, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None),
|
||||
/// Allows bounding the return type of AFIT/RPITIT.
|
||||
(incomplete, return_type_notation, "1.70.0", Some(109417), None),
|
||||
/// Allows `extern "rust-cold"`.
|
||||
|
@ -403,16 +403,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk
|
||||
),
|
||||
|
||||
// Debugging
|
||||
ungated!(
|
||||
debugger_visualizer, Normal,
|
||||
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), DuplicatesOk
|
||||
),
|
||||
|
||||
// ==========================================================================
|
||||
// Unstable attributes:
|
||||
// ==========================================================================
|
||||
|
||||
// RFC #3191: #[debugger_visualizer] support
|
||||
gated!(
|
||||
debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
|
||||
DuplicatesOk, experimental!(debugger_visualizer)
|
||||
),
|
||||
|
||||
// Linking:
|
||||
gated!(
|
||||
naked, Normal, template!(Word), WarnFollowing, @only_local: true,
|
||||
|
@ -293,6 +293,8 @@ language_item_table! {
|
||||
|
||||
PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
|
||||
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
|
||||
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
|
||||
|
@ -35,6 +35,10 @@ hir_analysis_field_already_declared =
|
||||
|
||||
hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
|
||||
|
||||
hir_analysis_const_param_ty_impl_on_non_adt =
|
||||
the trait `ConstParamTy` may not be implemented for this type
|
||||
.label = type is not a structure or enumeration
|
||||
|
||||
hir_analysis_ambiguous_lifetime_bound =
|
||||
ambiguous lifetime bound, explicit lifetime bound required
|
||||
|
||||
|
@ -56,6 +56,9 @@ use std::slice;
|
||||
#[derive(Debug)]
|
||||
pub struct PathSeg(pub DefId, pub usize);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct OnlySelfBounds(pub bool);
|
||||
|
||||
pub trait AstConv<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
|
||||
@ -670,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
args: &GenericArgs<'_>,
|
||||
infer_args: bool,
|
||||
self_ty: Ty<'tcx>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> GenericArgCountResult {
|
||||
let (substs, arg_count) = self.create_substs_for_ast_path(
|
||||
trait_ref_span,
|
||||
@ -706,6 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
&mut dup_bindings,
|
||||
binding_span.unwrap_or(binding.span),
|
||||
constness,
|
||||
only_self_bounds,
|
||||
);
|
||||
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
|
||||
}
|
||||
@ -741,6 +746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
speculative: bool,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> GenericArgCountResult {
|
||||
let hir_id = trait_ref.hir_ref_id;
|
||||
let binding_span = None;
|
||||
@ -766,6 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
args,
|
||||
infer_args,
|
||||
self_ty,
|
||||
only_self_bounds,
|
||||
)
|
||||
}
|
||||
|
||||
@ -777,6 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
args: &GenericArgs<'_>,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) {
|
||||
let binding_span = Some(span);
|
||||
let constness = ty::BoundConstness::NotConst;
|
||||
@ -799,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
args,
|
||||
infer_args,
|
||||
self_ty,
|
||||
only_self_bounds,
|
||||
);
|
||||
}
|
||||
|
||||
@ -947,6 +956,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ast_bounds: I,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) {
|
||||
for ast_bound in ast_bounds {
|
||||
match ast_bound {
|
||||
@ -964,11 +974,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
param_ty,
|
||||
bounds,
|
||||
false,
|
||||
only_self_bounds,
|
||||
);
|
||||
}
|
||||
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
|
||||
self.instantiate_lang_item_trait_ref(
|
||||
lang_item, span, hir_id, args, param_ty, bounds,
|
||||
lang_item,
|
||||
span,
|
||||
hir_id,
|
||||
args,
|
||||
param_ty,
|
||||
bounds,
|
||||
only_self_bounds,
|
||||
);
|
||||
}
|
||||
hir::GenericBound::Outlives(lifetime) => {
|
||||
@ -1006,8 +1023,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::GenericBound<'_>],
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> Bounds<'tcx> {
|
||||
self.compute_bounds_inner(param_ty, ast_bounds)
|
||||
let mut bounds = Bounds::default();
|
||||
self.add_bounds(
|
||||
param_ty,
|
||||
ast_bounds.iter(),
|
||||
&mut bounds,
|
||||
ty::List::empty(),
|
||||
only_self_bounds,
|
||||
);
|
||||
debug!(?bounds);
|
||||
|
||||
bounds
|
||||
}
|
||||
|
||||
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
||||
@ -1029,17 +1057,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
}
|
||||
|
||||
self.compute_bounds_inner(param_ty, &result)
|
||||
}
|
||||
|
||||
fn compute_bounds_inner(
|
||||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::GenericBound<'_>],
|
||||
) -> Bounds<'tcx> {
|
||||
let mut bounds = Bounds::default();
|
||||
|
||||
self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
|
||||
self.add_bounds(
|
||||
param_ty,
|
||||
result.iter(),
|
||||
&mut bounds,
|
||||
ty::List::empty(),
|
||||
OnlySelfBounds(true),
|
||||
);
|
||||
debug!(?bounds);
|
||||
|
||||
bounds
|
||||
@ -1062,6 +1087,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
dup_bindings: &mut FxHashMap<DefId, Span>,
|
||||
path_span: Span,
|
||||
constness: ty::BoundConstness,
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
@ -1361,8 +1387,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
//
|
||||
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
|
||||
// parameter to have a skipped binder.
|
||||
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
|
||||
self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
|
||||
//
|
||||
// NOTE: If `only_self_bounds` is true, do NOT expand this associated
|
||||
// type bound into a trait predicate, since we only want to add predicates
|
||||
// for the `Self` type.
|
||||
if !only_self_bounds.0 {
|
||||
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
|
||||
self.add_bounds(
|
||||
param_ty,
|
||||
ast_bounds.iter(),
|
||||
bounds,
|
||||
projection_ty.bound_vars(),
|
||||
only_self_bounds,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@ -1403,6 +1441,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
dummy_self,
|
||||
&mut bounds,
|
||||
false,
|
||||
// FIXME: This should be `true`, but we don't really handle
|
||||
// associated type bounds or type aliases in objects in a way
|
||||
// that makes this meaningful, I think.
|
||||
OnlySelfBounds(false),
|
||||
) {
|
||||
potential_assoc_types.extend(cur_potential_assoc_types);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
//! Check properties that are required by built-in traits and set
|
||||
//! up data structures required by type-checking/codegen.
|
||||
|
||||
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
|
||||
use crate::errors::{
|
||||
ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{struct_span_err, MultiSpan};
|
||||
use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::misc::{
|
||||
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
|
||||
type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
|
||||
ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
|
||||
};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||
@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
|
||||
Checker { tcx, trait_def_id }
|
||||
.check(lang_items.drop_trait(), visit_implementation_of_drop)
|
||||
.check(lang_items.copy_trait(), visit_implementation_of_copy)
|
||||
.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty)
|
||||
.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
|
||||
}
|
||||
@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
|
||||
Ok(()) => {}
|
||||
Err(CopyImplementationError::InfringingFields(fields)) => {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0204,
|
||||
"the trait `Copy` cannot be implemented for this type"
|
||||
);
|
||||
|
||||
// We'll try to suggest constraining type parameters to fulfill the requirements of
|
||||
// their `Copy` implementation.
|
||||
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
|
||||
let mut bounds = vec![];
|
||||
|
||||
let mut seen_tys = FxHashSet::default();
|
||||
|
||||
for (field, ty, reason) in fields {
|
||||
// Only report an error once per type.
|
||||
if !seen_tys.insert(ty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let field_span = tcx.def_span(field.did);
|
||||
err.span_label(field_span, "this field does not implement `Copy`");
|
||||
|
||||
match reason {
|
||||
InfringingFieldsReason::Fulfill(fulfillment_errors) => {
|
||||
for error in fulfillment_errors {
|
||||
let error_predicate = error.obligation.predicate;
|
||||
// Only note if it's not the root obligation, otherwise it's trivial and
|
||||
// should be self-explanatory (i.e. a field literally doesn't implement Copy).
|
||||
|
||||
// FIXME: This error could be more descriptive, especially if the error_predicate
|
||||
// contains a foreign type or if it's a deeply nested type...
|
||||
if error_predicate != error.root_obligation.predicate {
|
||||
errors
|
||||
.entry((ty.to_string(), error_predicate.to_string()))
|
||||
.or_default()
|
||||
.push(error.obligation.cause.span);
|
||||
}
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(
|
||||
ty::TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
..
|
||||
},
|
||||
)) = error_predicate.kind().skip_binder()
|
||||
{
|
||||
let ty = trait_ref.self_ty();
|
||||
if let ty::Param(_) = ty.kind() {
|
||||
bounds.push((
|
||||
format!("{ty}"),
|
||||
trait_ref.print_only_trait_path().to_string(),
|
||||
Some(trait_ref.def_id),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InfringingFieldsReason::Regions(region_errors) => {
|
||||
for error in region_errors {
|
||||
let ty = ty.to_string();
|
||||
match error {
|
||||
RegionResolutionError::ConcreteFailure(origin, a, b) => {
|
||||
let predicate = format!("{b}: {a}");
|
||||
errors
|
||||
.entry((ty.clone(), predicate.clone()))
|
||||
.or_default()
|
||||
.push(origin.span());
|
||||
if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
|
||||
bounds.push((b.to_string(), a.to_string(), None));
|
||||
}
|
||||
}
|
||||
RegionResolutionError::GenericBoundFailure(origin, a, b) => {
|
||||
let predicate = format!("{a}: {b}");
|
||||
errors
|
||||
.entry((ty.clone(), predicate.clone()))
|
||||
.or_default()
|
||||
.push(origin.span());
|
||||
if let infer::region_constraints::GenericKind::Param(_) = a {
|
||||
bounds.push((a.to_string(), b.to_string(), None));
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for ((ty, error_predicate), spans) in errors {
|
||||
let span: MultiSpan = spans.into();
|
||||
err.span_note(
|
||||
span,
|
||||
&format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
|
||||
);
|
||||
}
|
||||
suggest_constraining_type_params(
|
||||
tcx,
|
||||
tcx.hir().get_generics(impl_did).expect("impls always have generics"),
|
||||
&mut err,
|
||||
bounds.iter().map(|(param, constraint, def_id)| {
|
||||
(param.as_str(), constraint.as_str(), *def_id)
|
||||
}),
|
||||
None,
|
||||
);
|
||||
err.emit();
|
||||
infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span);
|
||||
}
|
||||
Err(CopyImplementationError::NotAnAdt) => {
|
||||
tcx.sess.emit_err(CopyImplOnNonAdt { span });
|
||||
@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
let self_type = tcx.type_of(impl_did).subst_identity();
|
||||
assert!(!self_type.has_escaping_bound_vars());
|
||||
|
||||
let param_env = tcx.param_env(impl_did);
|
||||
|
||||
let span = match tcx.hir().expect_item(impl_did).expect_impl() {
|
||||
hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
|
||||
impl_ => impl_.self_ty.span,
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(span, impl_did);
|
||||
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
|
||||
Ok(()) => {}
|
||||
Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
|
||||
infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span);
|
||||
}
|
||||
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
|
||||
tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||
debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
|
||||
|
||||
@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
|
||||
|
||||
CoerceUnsizedInfo { custom_kind: kind }
|
||||
}
|
||||
|
||||
fn infringing_fields_error(
|
||||
tcx: TyCtxt<'_>,
|
||||
fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>,
|
||||
lang_item: LangItem,
|
||||
impl_did: LocalDefId,
|
||||
impl_span: Span,
|
||||
) -> ErrorGuaranteed {
|
||||
let trait_did = tcx.require_lang_item(lang_item, Some(impl_span));
|
||||
|
||||
let trait_name = tcx.def_path_str(trait_did);
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
impl_span,
|
||||
E0204,
|
||||
"the trait `{trait_name}` cannot be implemented for this type"
|
||||
);
|
||||
|
||||
// We'll try to suggest constraining type parameters to fulfill the requirements of
|
||||
// their `Copy` implementation.
|
||||
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
|
||||
let mut bounds = vec![];
|
||||
|
||||
let mut seen_tys = FxHashSet::default();
|
||||
|
||||
for (field, ty, reason) in fields {
|
||||
// Only report an error once per type.
|
||||
if !seen_tys.insert(ty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let field_span = tcx.def_span(field.did);
|
||||
err.span_label(field_span, format!("this field does not implement `{trait_name}`"));
|
||||
|
||||
match reason {
|
||||
InfringingFieldsReason::Fulfill(fulfillment_errors) => {
|
||||
for error in fulfillment_errors {
|
||||
let error_predicate = error.obligation.predicate;
|
||||
// Only note if it's not the root obligation, otherwise it's trivial and
|
||||
// should be self-explanatory (i.e. a field literally doesn't implement Copy).
|
||||
|
||||
// FIXME: This error could be more descriptive, especially if the error_predicate
|
||||
// contains a foreign type or if it's a deeply nested type...
|
||||
if error_predicate != error.root_obligation.predicate {
|
||||
errors
|
||||
.entry((ty.to_string(), error_predicate.to_string()))
|
||||
.or_default()
|
||||
.push(error.obligation.cause.span);
|
||||
}
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
..
|
||||
})) = error_predicate.kind().skip_binder()
|
||||
{
|
||||
let ty = trait_ref.self_ty();
|
||||
if let ty::Param(_) = ty.kind() {
|
||||
bounds.push((
|
||||
format!("{ty}"),
|
||||
trait_ref.print_only_trait_path().to_string(),
|
||||
Some(trait_ref.def_id),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InfringingFieldsReason::Regions(region_errors) => {
|
||||
for error in region_errors {
|
||||
let ty = ty.to_string();
|
||||
match error {
|
||||
RegionResolutionError::ConcreteFailure(origin, a, b) => {
|
||||
let predicate = format!("{b}: {a}");
|
||||
errors
|
||||
.entry((ty.clone(), predicate.clone()))
|
||||
.or_default()
|
||||
.push(origin.span());
|
||||
if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
|
||||
bounds.push((b.to_string(), a.to_string(), None));
|
||||
}
|
||||
}
|
||||
RegionResolutionError::GenericBoundFailure(origin, a, b) => {
|
||||
let predicate = format!("{a}: {b}");
|
||||
errors
|
||||
.entry((ty.clone(), predicate.clone()))
|
||||
.or_default()
|
||||
.push(origin.span());
|
||||
if let infer::region_constraints::GenericKind::Param(_) = a {
|
||||
bounds.push((a.to_string(), b.to_string(), None));
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for ((ty, error_predicate), spans) in errors {
|
||||
let span: MultiSpan = spans.into();
|
||||
err.span_note(
|
||||
span,
|
||||
format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
|
||||
);
|
||||
}
|
||||
suggest_constraining_type_params(
|
||||
tcx,
|
||||
tcx.hir().get_generics(impl_did).expect("impls always have generics"),
|
||||
&mut err,
|
||||
bounds
|
||||
.iter()
|
||||
.map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
|
||||
None,
|
||||
);
|
||||
|
||||
err.emit()
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::ItemCtxt;
|
||||
use crate::astconv::AstConv;
|
||||
use crate::astconv::{AstConv, OnlySelfBounds};
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>(
|
||||
);
|
||||
|
||||
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
|
||||
// Associated types are implicitly sized unless a `?Sized` bound is found
|
||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||
|
||||
@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>(
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
ty::print::with_no_queries!({
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
|
||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||
debug!(?bounds);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::astconv::AstConv;
|
||||
use crate::astconv::{AstConv, OnlySelfBounds};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::ItemCtxt;
|
||||
use crate::constrained_generic_params as cgp;
|
||||
@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct OnlySelfBounds(bool);
|
||||
|
||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
||||
/// `Self: Trait` predicates for traits.
|
||||
@ -99,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
| ItemKind::Struct(_, generics)
|
||||
| ItemKind::Union(_, generics) => generics,
|
||||
|
||||
ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
|
||||
is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
|
||||
ItemKind::Trait(_, _, generics, self_bounds, ..)
|
||||
| ItemKind::TraitAlias(generics, self_bounds) => {
|
||||
is_trait = Some(self_bounds);
|
||||
generics
|
||||
}
|
||||
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
|
||||
@ -122,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
|
||||
// Below we'll consider the bounds on the type parameters (including `Self`)
|
||||
// and the explicit where-clauses, but to get the full set of predicates
|
||||
// on a trait we need to add in the supertrait bounds and bounds found on
|
||||
// associated types.
|
||||
if let Some(_trait_ref) = is_trait {
|
||||
predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
|
||||
// on a trait we must also consider the bounds that follow the trait's name,
|
||||
// like `trait Foo: A + B + C`.
|
||||
if let Some(self_bounds) = is_trait {
|
||||
predicates.extend(
|
||||
icx.astconv()
|
||||
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
|
||||
.predicates(),
|
||||
);
|
||||
}
|
||||
|
||||
// In default impls, we can assume that the self type implements
|
||||
@ -225,7 +227,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
}
|
||||
|
||||
let mut bounds = Bounds::default();
|
||||
icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
|
||||
icx.astconv().add_bounds(
|
||||
ty,
|
||||
bound_pred.bounds.iter(),
|
||||
&mut bounds,
|
||||
bound_vars,
|
||||
OnlySelfBounds(false),
|
||||
);
|
||||
predicates.extend(bounds.predicates());
|
||||
}
|
||||
|
||||
@ -608,7 +616,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||
let (superbounds, where_bounds_that_match) = match filter {
|
||||
PredicateFilter::All => (
|
||||
// Convert the bounds that follow the colon (or equal in trait aliases)
|
||||
icx.astconv().compute_bounds(self_param_ty, bounds),
|
||||
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
|
||||
// Also include all where clause bounds
|
||||
icx.type_parameter_bounds_in_generics(
|
||||
generics,
|
||||
@ -620,7 +628,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||
),
|
||||
PredicateFilter::SelfOnly => (
|
||||
// Convert the bounds that follow the colon (or equal in trait aliases)
|
||||
icx.astconv().compute_bounds(self_param_ty, bounds),
|
||||
icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
|
||||
// Include where clause bounds for `Self`
|
||||
icx.type_parameter_bounds_in_generics(
|
||||
generics,
|
||||
@ -774,32 +782,35 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||
only_self_bounds: OnlySelfBounds,
|
||||
assoc_name: Option<Ident>,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
ast_generics
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|wp| match wp {
|
||||
hir::WherePredicate::BoundPredicate(bp) => Some(bp),
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|bp| {
|
||||
let bt = if bp.is_param_bound(param_def_id.to_def_id()) {
|
||||
Some(ty)
|
||||
} else if !only_self_bounds.0 {
|
||||
Some(self.to_ty(bp.bounded_ty))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let bvars = self.tcx.late_bound_vars(bp.hir_id);
|
||||
let mut bounds = Bounds::default();
|
||||
|
||||
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
|
||||
|(_, b, _)| match assoc_name {
|
||||
Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
|
||||
None => true,
|
||||
},
|
||||
)
|
||||
})
|
||||
.flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
|
||||
.collect()
|
||||
for predicate in ast_generics.predicates {
|
||||
let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
|
||||
ty
|
||||
} else if !only_self_bounds.0 {
|
||||
self.to_ty(predicate.bounded_ty)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
|
||||
self.astconv().add_bounds(
|
||||
bound_ty,
|
||||
predicate.bounds.iter().filter(|bound| {
|
||||
assoc_name
|
||||
.map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
|
||||
}),
|
||||
&mut bounds,
|
||||
bound_vars,
|
||||
only_self_bounds,
|
||||
);
|
||||
}
|
||||
|
||||
bounds.predicates().collect()
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
@ -817,19 +828,3 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a specific `GenericBound` from the AST into a set of
|
||||
/// predicates that apply to the self type. A vector is returned
|
||||
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
|
||||
/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
|
||||
/// and `<T as Bar>::X == i32`).
|
||||
fn predicates_from_bound<'tcx>(
|
||||
astconv: &dyn AstConv<'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
bound: &'tcx hir::GenericBound<'tcx>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let mut bounds = Bounds::default();
|
||||
astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
|
||||
bounds.predicates().collect()
|
||||
}
|
||||
|
@ -107,6 +107,14 @@ pub struct CopyImplOnNonAdt {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
|
||||
pub struct ConstParamTyImplOnNonAdt {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
|
||||
pub struct TraitObjectDeclaredWithNoTraits {
|
||||
|
@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
|
||||
|
||||
use std::ops::Not;
|
||||
|
||||
use astconv::AstConv;
|
||||
use astconv::{AstConv, OnlySelfBounds};
|
||||
use bounds::Bounds;
|
||||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
@ -531,6 +531,7 @@ pub fn hir_trait_to_predicates<'tcx>(
|
||||
self_ty,
|
||||
&mut bounds,
|
||||
true,
|
||||
OnlySelfBounds(false),
|
||||
);
|
||||
|
||||
bounds
|
||||
|
@ -50,6 +50,14 @@ lint_deprecated_lint_name =
|
||||
lint_renamed_or_removed_lint = {$msg}
|
||||
.suggestion = use the new name
|
||||
|
||||
lint_suspicious_double_ref_op =
|
||||
using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
|
||||
*[should_not_happen] [{$op}]
|
||||
[deref] dereferencing
|
||||
[borrow] borrowing
|
||||
[clone] cloning
|
||||
} the inner type
|
||||
|
||||
lint_unknown_lint =
|
||||
unknown lint: `{$name}`
|
||||
.suggestion = did you mean
|
||||
|
@ -1150,6 +1150,14 @@ pub struct NoopMethodCallDiag<'a> {
|
||||
pub label: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_suspicious_double_ref_op)]
|
||||
pub struct SuspiciousDoubleRefDiag<'a> {
|
||||
pub call: Symbol,
|
||||
pub ty: Ty<'a>,
|
||||
pub op: &'static str,
|
||||
}
|
||||
|
||||
// pass_by_value.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_pass_by_value)]
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::context::LintContext;
|
||||
use crate::lints::NoopMethodCallDiag;
|
||||
use crate::lints::{NoopMethodCallDiag, SuspiciousDoubleRefDiag};
|
||||
use crate::LateContext;
|
||||
use crate::LateLintPass;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
declare_lint! {
|
||||
@ -35,14 +36,44 @@ declare_lint! {
|
||||
"detects the use of well-known noop methods"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]);
|
||||
declare_lint! {
|
||||
/// The `suspicious_double_ref_op` lint checks for usage of `.clone()`/`.borrow()`/`.deref()`
|
||||
/// on an `&&T` when `T: !Deref/Borrow/Clone`, which means the call will return the inner `&T`,
|
||||
/// instead of performing the operation on the underlying `T` and can be confusing.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused)]
|
||||
/// struct Foo;
|
||||
/// let foo = &&Foo;
|
||||
/// let clone: &Foo = foo.clone();
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Since `Foo` doesn't implement `Clone`, running `.clone()` only dereferences the double
|
||||
/// reference, instead of cloning the inner type which should be what was intended.
|
||||
pub SUSPICIOUS_DOUBLE_REF_OP,
|
||||
Warn,
|
||||
"suspicious call of trait method on `&&T`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL, SUSPICIOUS_DOUBLE_REF_OP]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
// We only care about method calls.
|
||||
let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else {
|
||||
return
|
||||
let ExprKind::MethodCall(call, receiver, _, call_span) = &expr.kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
if call_span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
|
||||
// traits and ignore any other method call.
|
||||
let did = match cx.typeck_results().type_dependent_def(expr.hir_id) {
|
||||
@ -70,25 +101,39 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
};
|
||||
// (Re)check that it implements the noop diagnostic.
|
||||
let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
|
||||
if !matches!(
|
||||
name,
|
||||
sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let op = match name {
|
||||
sym::noop_method_borrow => "borrow",
|
||||
sym::noop_method_clone => "clone",
|
||||
sym::noop_method_deref => "deref",
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let receiver_ty = cx.typeck_results().expr_ty(receiver);
|
||||
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
|
||||
if receiver_ty != expr_ty {
|
||||
// This lint will only trigger if the receiver type and resulting expression \
|
||||
// type are the same, implying that the method call is unnecessary.
|
||||
let arg_adjustments = cx.typeck_results().expr_adjustments(receiver);
|
||||
|
||||
// If there is any user defined auto-deref step, then we don't want to warn.
|
||||
// https://github.com/rust-lang/rust-clippy/issues/9272
|
||||
if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
let expr_span = expr.span;
|
||||
let span = expr_span.with_lo(receiver.span.hi());
|
||||
cx.emit_spanned_lint(
|
||||
NOOP_METHOD_CALL,
|
||||
span,
|
||||
NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
|
||||
);
|
||||
|
||||
if receiver_ty == expr_ty {
|
||||
cx.emit_spanned_lint(
|
||||
NOOP_METHOD_CALL,
|
||||
span,
|
||||
NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
|
||||
);
|
||||
} else {
|
||||
cx.emit_spanned_lint(
|
||||
SUSPICIOUS_DOUBLE_REF_OP,
|
||||
span,
|
||||
SuspiciousDoubleRefDiag { call: call.ident.name, ty: expr_ty, op },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -531,6 +531,7 @@ symbols! {
|
||||
const_mut_refs,
|
||||
const_panic,
|
||||
const_panic_fmt,
|
||||
const_param_ty,
|
||||
const_precise_live_drops,
|
||||
const_raw_ptr_deref,
|
||||
const_raw_ptr_to_usize_cast,
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
use crate::traits::{self, ObligationCause, ObligationCtxt};
|
||||
|
||||
use hir::LangItem;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, AdtDef, GenericArg, List, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use super::outlives_bounds::InferCtxtExt;
|
||||
@ -19,6 +20,11 @@ pub enum CopyImplementationError<'tcx> {
|
||||
HasDestructor,
|
||||
}
|
||||
|
||||
pub enum ConstParamTyImplementationError<'tcx> {
|
||||
InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
|
||||
NotAnAdtOrBuiltinAllowed,
|
||||
}
|
||||
|
||||
pub enum InfringingFieldsReason<'tcx> {
|
||||
Fulfill(Vec<FulfillmentError<'tcx>>),
|
||||
Regions(Vec<RegionResolutionError<'tcx>>),
|
||||
@ -27,7 +33,10 @@ pub enum InfringingFieldsReason<'tcx> {
|
||||
/// Checks that the fields of the type (an ADT) all implement copy.
|
||||
///
|
||||
/// If fields don't implement copy, return an error containing a list of
|
||||
/// those violating fields. If it's not an ADT, returns `Err(NotAnAdt)`.
|
||||
/// those violating fields.
|
||||
///
|
||||
/// If it's not an ADT, int ty, `bool`, float ty, `char`, raw pointer, `!`,
|
||||
/// a reference or an array returns `Err(NotAnAdt)`.
|
||||
pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
@ -47,12 +56,82 @@ pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
| ty::Ref(_, _, hir::Mutability::Not)
|
||||
| ty::Array(..) => return Ok(()),
|
||||
|
||||
ty::Adt(adt, substs) => (adt, substs),
|
||||
&ty::Adt(adt, substs) => (adt, substs),
|
||||
|
||||
_ => return Err(CopyImplementationError::NotAnAdt),
|
||||
};
|
||||
|
||||
let copy_def_id = tcx.require_lang_item(hir::LangItem::Copy, Some(parent_cause.span));
|
||||
all_fields_implement_trait(
|
||||
tcx,
|
||||
param_env,
|
||||
self_type,
|
||||
adt,
|
||||
substs,
|
||||
parent_cause,
|
||||
hir::LangItem::Copy,
|
||||
)
|
||||
.map_err(CopyImplementationError::InfringingFields)?;
|
||||
|
||||
if adt.has_dtor(tcx) {
|
||||
return Err(CopyImplementationError::HasDestructor);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks that the fields of the type (an ADT) all implement `ConstParamTy`.
|
||||
///
|
||||
/// If fields don't implement `ConstParamTy`, return an error containing a list of
|
||||
/// those violating fields.
|
||||
///
|
||||
/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
|
||||
pub fn type_allowed_to_implement_const_param_ty<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
self_type: Ty<'tcx>,
|
||||
parent_cause: ObligationCause<'tcx>,
|
||||
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
|
||||
let (adt, substs) = match self_type.kind() {
|
||||
// `core` provides these impls.
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
| ty::Bool
|
||||
| ty::Char
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Slice(_)
|
||||
| ty::Ref(.., hir::Mutability::Not) => return Ok(()),
|
||||
|
||||
&ty::Adt(adt, substs) => (adt, substs),
|
||||
|
||||
_ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
|
||||
};
|
||||
|
||||
all_fields_implement_trait(
|
||||
tcx,
|
||||
param_env,
|
||||
self_type,
|
||||
adt,
|
||||
substs,
|
||||
parent_cause,
|
||||
hir::LangItem::ConstParamTy,
|
||||
)
|
||||
.map_err(ConstParamTyImplementationError::InfrigingFields)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check that all fields of a given `adt` implement `lang_item` trait.
|
||||
pub fn all_fields_implement_trait<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
self_type: Ty<'tcx>,
|
||||
adt: AdtDef<'tcx>,
|
||||
substs: &'tcx List<GenericArg<'tcx>>,
|
||||
parent_cause: ObligationCause<'tcx>,
|
||||
lang_item: LangItem,
|
||||
) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> {
|
||||
let trait_def_id = tcx.require_lang_item(lang_item, Some(parent_cause.span));
|
||||
|
||||
let mut infringing = Vec::new();
|
||||
for variant in adt.variants() {
|
||||
@ -93,7 +172,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
// between expected and found const-generic types. Don't report an
|
||||
// additional copy error here, since it's not typically useful.
|
||||
if !normalization_errors.is_empty() || ty.references_error() {
|
||||
tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking Copy implementation"));
|
||||
tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking {tr} implementation", tr = tcx.def_path_str(trait_def_id)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -101,7 +180,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
ObligationCause::dummy_with_span(field_ty_span),
|
||||
param_env,
|
||||
ty,
|
||||
copy_def_id,
|
||||
trait_def_id,
|
||||
);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
@ -124,15 +203,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
if !infringing.is_empty() {
|
||||
return Err(CopyImplementationError::InfringingFields(infringing));
|
||||
}
|
||||
|
||||
if adt.has_dtor(tcx) {
|
||||
return Err(CopyImplementationError::HasDestructor);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if infringing.is_empty() { Ok(()) } else { Err(infringing) }
|
||||
}
|
||||
|
||||
pub fn check_tys_might_be_eq<'tcx>(
|
||||
|
@ -9,10 +9,10 @@
|
||||
|
||||
#![stable(feature = "core_ascii", since = "1.26.0")]
|
||||
|
||||
use crate::escape;
|
||||
use crate::fmt;
|
||||
use crate::iter::FusedIterator;
|
||||
use crate::ops::Range;
|
||||
use crate::str::from_utf8_unchecked;
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
/// An iterator over the escaped version of a byte.
|
||||
///
|
||||
@ -21,10 +21,7 @@ use crate::str::from_utf8_unchecked;
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct EscapeDefault {
|
||||
range: Range<u8>,
|
||||
data: [u8; 4],
|
||||
}
|
||||
pub struct EscapeDefault(escape::EscapeIterInner<4>);
|
||||
|
||||
/// Returns an iterator that produces an escaped version of a `u8`.
|
||||
///
|
||||
@ -90,21 +87,9 @@ pub struct EscapeDefault {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn escape_default(c: u8) -> EscapeDefault {
|
||||
let (data, len) = match c {
|
||||
b'\t' => ([b'\\', b't', 0, 0], 2),
|
||||
b'\r' => ([b'\\', b'r', 0, 0], 2),
|
||||
b'\n' => ([b'\\', b'n', 0, 0], 2),
|
||||
b'\\' => ([b'\\', b'\\', 0, 0], 2),
|
||||
b'\'' => ([b'\\', b'\'', 0, 0], 2),
|
||||
b'"' => ([b'\\', b'"', 0, 0], 2),
|
||||
b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
|
||||
_ => {
|
||||
let hex_digits: &[u8; 16] = b"0123456789abcdef";
|
||||
([b'\\', b'x', hex_digits[(c >> 4) as usize], hex_digits[(c & 0xf) as usize]], 4)
|
||||
}
|
||||
};
|
||||
|
||||
return EscapeDefault { range: 0..len, data };
|
||||
let mut data = [0; 4];
|
||||
let range = escape::escape_ascii_into(&mut data, c);
|
||||
EscapeDefault(escape::EscapeIterInner::new(data, range))
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -113,33 +98,59 @@ impl Iterator for EscapeDefault {
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
self.range.next().map(|i| self.data[i as usize])
|
||||
self.0.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.range.size_hint()
|
||||
let n = self.0.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<u8> {
|
||||
self.next_back()
|
||||
self.0.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.0.advance_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl DoubleEndedIterator for EscapeDefault {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<u8> {
|
||||
self.range.next_back().map(|i| self.data[i as usize])
|
||||
self.0.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.0.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExactSizeIterator for EscapeDefault {}
|
||||
impl ExactSizeIterator for EscapeDefault {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeDefault {}
|
||||
|
||||
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
|
||||
impl fmt::Display for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// SAFETY: ok because `escape_default` created only valid utf-8 data
|
||||
f.write_str(unsafe {
|
||||
from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
|
||||
})
|
||||
f.write_str(self.0.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,20 +380,7 @@ impl char {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn escape_unicode(self) -> EscapeUnicode {
|
||||
let c = self as u32;
|
||||
|
||||
// or-ing 1 ensures that for c==0 the code computes that one
|
||||
// digit should be printed and (which is the same) avoids the
|
||||
// (31 - 32) underflow
|
||||
let msb = 31 - (c | 1).leading_zeros();
|
||||
|
||||
// the index of the most significant hex digit
|
||||
let ms_hex_digit = msb / 4;
|
||||
EscapeUnicode {
|
||||
c: self,
|
||||
state: EscapeUnicodeState::Backslash,
|
||||
hex_digit_idx: ms_hex_digit as usize,
|
||||
}
|
||||
EscapeUnicode::new(self)
|
||||
}
|
||||
|
||||
/// An extended version of `escape_debug` that optionally permits escaping
|
||||
@ -403,21 +390,20 @@ impl char {
|
||||
/// characters, and double quotes in strings.
|
||||
#[inline]
|
||||
pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
|
||||
let init_state = match self {
|
||||
'\0' => EscapeDefaultState::Backslash('0'),
|
||||
'\t' => EscapeDefaultState::Backslash('t'),
|
||||
'\r' => EscapeDefaultState::Backslash('r'),
|
||||
'\n' => EscapeDefaultState::Backslash('n'),
|
||||
'\\' => EscapeDefaultState::Backslash(self),
|
||||
'"' if args.escape_double_quote => EscapeDefaultState::Backslash(self),
|
||||
'\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self),
|
||||
match self {
|
||||
'\0' => EscapeDebug::backslash(b'0'),
|
||||
'\t' => EscapeDebug::backslash(b't'),
|
||||
'\r' => EscapeDebug::backslash(b'r'),
|
||||
'\n' => EscapeDebug::backslash(b'n'),
|
||||
'\\' => EscapeDebug::backslash(b'\\'),
|
||||
'"' if args.escape_double_quote => EscapeDebug::backslash(b'"'),
|
||||
'\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''),
|
||||
_ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
|
||||
EscapeDefaultState::Unicode(self.escape_unicode())
|
||||
EscapeDebug::from_unicode(self.escape_unicode())
|
||||
}
|
||||
_ if is_printable(self) => EscapeDefaultState::Char(self),
|
||||
_ => EscapeDefaultState::Unicode(self.escape_unicode()),
|
||||
};
|
||||
EscapeDebug(EscapeDefault { state: init_state })
|
||||
_ if is_printable(self) => EscapeDebug::printable(self),
|
||||
_ => EscapeDebug::from_unicode(self.escape_unicode()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the literal escape code of a character
|
||||
@ -515,15 +501,14 @@ impl char {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn escape_default(self) -> EscapeDefault {
|
||||
let init_state = match self {
|
||||
'\t' => EscapeDefaultState::Backslash('t'),
|
||||
'\r' => EscapeDefaultState::Backslash('r'),
|
||||
'\n' => EscapeDefaultState::Backslash('n'),
|
||||
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
|
||||
'\x20'..='\x7e' => EscapeDefaultState::Char(self),
|
||||
_ => EscapeDefaultState::Unicode(self.escape_unicode()),
|
||||
};
|
||||
EscapeDefault { state: init_state }
|
||||
match self {
|
||||
'\t' => EscapeDefault::backslash(b't'),
|
||||
'\r' => EscapeDefault::backslash(b'r'),
|
||||
'\n' => EscapeDefault::backslash(b'n'),
|
||||
'\\' | '\'' | '"' => EscapeDefault::backslash(self as u8),
|
||||
'\x20'..='\x7e' => EscapeDefault::printable(self as u8),
|
||||
_ => EscapeDefault::from_unicode(self.escape_unicode()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of bytes this `char` would need if encoded in UTF-8.
|
||||
|
@ -39,8 +39,10 @@ pub use self::methods::encode_utf16_raw;
|
||||
pub use self::methods::encode_utf8_raw;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::escape;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::iter::FusedIterator;
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
pub(crate) use self::methods::EscapeDebugExtArgs;
|
||||
|
||||
@ -146,86 +148,44 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
|
||||
/// [`escape_unicode`]: char::escape_unicode
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct EscapeUnicode {
|
||||
c: char,
|
||||
state: EscapeUnicodeState,
|
||||
pub struct EscapeUnicode(escape::EscapeIterInner<10>);
|
||||
|
||||
// The index of the next hex digit to be printed (0 if none),
|
||||
// i.e., the number of remaining hex digits to be printed;
|
||||
// increasing from the least significant digit: 0x543210
|
||||
hex_digit_idx: usize,
|
||||
}
|
||||
|
||||
// The enum values are ordered so that their representation is the
|
||||
// same as the remaining length (besides the hexadecimal digits). This
|
||||
// likely makes `len()` a single load from memory) and inline-worth.
|
||||
#[derive(Clone, Debug)]
|
||||
enum EscapeUnicodeState {
|
||||
Done,
|
||||
RightBrace,
|
||||
Value,
|
||||
LeftBrace,
|
||||
Type,
|
||||
Backslash,
|
||||
impl EscapeUnicode {
|
||||
fn new(chr: char) -> Self {
|
||||
let mut data = [0; 10];
|
||||
let range = escape::escape_unicode_into(&mut data, chr);
|
||||
Self(escape::EscapeIterInner::new(data, range))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for EscapeUnicode {
|
||||
type Item = char;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeUnicodeState::Backslash => {
|
||||
self.state = EscapeUnicodeState::Type;
|
||||
Some('\\')
|
||||
}
|
||||
EscapeUnicodeState::Type => {
|
||||
self.state = EscapeUnicodeState::LeftBrace;
|
||||
Some('u')
|
||||
}
|
||||
EscapeUnicodeState::LeftBrace => {
|
||||
self.state = EscapeUnicodeState::Value;
|
||||
Some('{')
|
||||
}
|
||||
EscapeUnicodeState::Value => {
|
||||
let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
|
||||
let c = char::from_digit(hex_digit, 16).unwrap();
|
||||
if self.hex_digit_idx == 0 {
|
||||
self.state = EscapeUnicodeState::RightBrace;
|
||||
} else {
|
||||
self.hex_digit_idx -= 1;
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
EscapeUnicodeState::RightBrace => {
|
||||
self.state = EscapeUnicodeState::Done;
|
||||
Some('}')
|
||||
}
|
||||
EscapeUnicodeState::Done => None,
|
||||
}
|
||||
self.0.next().map(char::from)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = self.len();
|
||||
let n = self.0.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn last(self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeUnicodeState::Done => None,
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<char> {
|
||||
self.0.next_back().map(char::from)
|
||||
}
|
||||
|
||||
EscapeUnicodeState::RightBrace
|
||||
| EscapeUnicodeState::Value
|
||||
| EscapeUnicodeState::LeftBrace
|
||||
| EscapeUnicodeState::Type
|
||||
| EscapeUnicodeState::Backslash => Some('}'),
|
||||
}
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.0.advance_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,16 +193,7 @@ impl Iterator for EscapeUnicode {
|
||||
impl ExactSizeIterator for EscapeUnicode {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
// The match is a single memory access with no branching
|
||||
self.hex_digit_idx
|
||||
+ match self.state {
|
||||
EscapeUnicodeState::Done => 0,
|
||||
EscapeUnicodeState::RightBrace => 1,
|
||||
EscapeUnicodeState::Value => 2,
|
||||
EscapeUnicodeState::LeftBrace => 3,
|
||||
EscapeUnicodeState::Type => 4,
|
||||
EscapeUnicodeState::Backslash => 5,
|
||||
}
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,10 +203,7 @@ impl FusedIterator for EscapeUnicode {}
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for EscapeUnicode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for c in self.clone() {
|
||||
f.write_char(c)?;
|
||||
}
|
||||
Ok(())
|
||||
f.write_str(self.0.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,90 +215,60 @@ impl fmt::Display for EscapeUnicode {
|
||||
/// [`escape_default`]: char::escape_default
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct EscapeDefault {
|
||||
state: EscapeDefaultState,
|
||||
}
|
||||
pub struct EscapeDefault(escape::EscapeIterInner<10>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum EscapeDefaultState {
|
||||
Done,
|
||||
Char(char),
|
||||
Backslash(char),
|
||||
Unicode(EscapeUnicode),
|
||||
impl EscapeDefault {
|
||||
fn printable(chr: u8) -> Self {
|
||||
let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
Self(escape::EscapeIterInner::new(data, 0..1))
|
||||
}
|
||||
|
||||
fn backslash(chr: u8) -> Self {
|
||||
let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
Self(escape::EscapeIterInner::new(data, 0..2))
|
||||
}
|
||||
|
||||
fn from_unicode(esc: EscapeUnicode) -> Self {
|
||||
Self(esc.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for EscapeDefault {
|
||||
type Item = char;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Backslash(c) => {
|
||||
self.state = EscapeDefaultState::Char(c);
|
||||
Some('\\')
|
||||
}
|
||||
EscapeDefaultState::Char(c) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
Some(c)
|
||||
}
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
|
||||
}
|
||||
self.0.next().map(char::from)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = self.len();
|
||||
let n = self.0.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Backslash(c) if n == 0 => {
|
||||
self.state = EscapeDefaultState::Char(c);
|
||||
Some('\\')
|
||||
}
|
||||
EscapeDefaultState::Backslash(c) if n == 1 => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
Some(c)
|
||||
}
|
||||
EscapeDefaultState::Backslash(_) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
None
|
||||
}
|
||||
EscapeDefaultState::Char(c) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
|
||||
if n == 0 { Some(c) } else { None }
|
||||
}
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Unicode(ref mut i) => i.nth(n),
|
||||
}
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<char> {
|
||||
self.0.next_back().map(char::from)
|
||||
}
|
||||
|
||||
fn last(self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Unicode(iter) => iter.last(),
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
|
||||
}
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.0.advance_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "exact_size_escape", since = "1.11.0")]
|
||||
impl ExactSizeIterator for EscapeDefault {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
match self.state {
|
||||
EscapeDefaultState::Done => 0,
|
||||
EscapeDefaultState::Char(_) => 1,
|
||||
EscapeDefaultState::Backslash(_) => 2,
|
||||
EscapeDefaultState::Unicode(ref iter) => iter.len(),
|
||||
}
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,10 +278,7 @@ impl FusedIterator for EscapeDefault {}
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for c in self.clone() {
|
||||
f.write_char(c)?;
|
||||
}
|
||||
Ok(())
|
||||
f.write_str(self.0.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,21 +290,74 @@ impl fmt::Display for EscapeDefault {
|
||||
/// [`escape_debug`]: char::escape_debug
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EscapeDebug(EscapeDefault);
|
||||
pub struct EscapeDebug(EscapeDebugInner);
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl Iterator for EscapeDebug {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
#[derive(Clone, Debug)]
|
||||
// Note: It’s possible to manually encode the EscapeDebugInner inside of
|
||||
// EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] holds
|
||||
// a char) which would likely result in a more optimised code. For now we use
|
||||
// the option easier to implement.
|
||||
enum EscapeDebugInner {
|
||||
Bytes(escape::EscapeIterInner<10>),
|
||||
Char(char),
|
||||
}
|
||||
|
||||
impl EscapeDebug {
|
||||
fn printable(chr: char) -> Self {
|
||||
Self(EscapeDebugInner::Char(chr))
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
|
||||
fn backslash(chr: u8) -> Self {
|
||||
let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let iter = escape::EscapeIterInner::new(data, 0..2);
|
||||
Self(EscapeDebugInner::Bytes(iter))
|
||||
}
|
||||
|
||||
fn from_unicode(esc: EscapeUnicode) -> Self {
|
||||
Self(EscapeDebugInner::Bytes(esc.0))
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
let bytes = escape::EscapeIterInner::new([0; 10], 0..0);
|
||||
self.0 = EscapeDebugInner::Bytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl ExactSizeIterator for EscapeDebug {}
|
||||
impl Iterator for EscapeDebug {
|
||||
type Item = char;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.0 {
|
||||
EscapeDebugInner::Bytes(ref mut bytes) => bytes.next().map(char::from),
|
||||
EscapeDebugInner::Char(chr) => {
|
||||
self.clear();
|
||||
Some(chr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = self.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl ExactSizeIterator for EscapeDebug {
|
||||
fn len(&self) -> usize {
|
||||
match &self.0 {
|
||||
EscapeDebugInner::Bytes(bytes) => bytes.len(),
|
||||
EscapeDebugInner::Char(_) => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeDebug {}
|
||||
@ -397,7 +365,10 @@ impl FusedIterator for EscapeDebug {}
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl fmt::Display for EscapeDebug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
match &self.0 {
|
||||
EscapeDebugInner::Bytes(bytes) => f.write_str(bytes.as_str()),
|
||||
EscapeDebugInner::Char(chr) => f.write_char(*chr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
99
library/core/src/escape.rs
Normal file
99
library/core/src/escape.rs
Normal file
@ -0,0 +1,99 @@
|
||||
//! Helper code for character escaping.
|
||||
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::Range;
|
||||
|
||||
const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
|
||||
|
||||
/// Escapes a byte into provided buffer; returns length of escaped
|
||||
/// representation.
|
||||
pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> {
|
||||
let (data, len) = match byte {
|
||||
b'\t' => ([b'\\', b't', 0, 0], 2),
|
||||
b'\r' => ([b'\\', b'r', 0, 0], 2),
|
||||
b'\n' => ([b'\\', b'n', 0, 0], 2),
|
||||
b'\\' => ([b'\\', b'\\', 0, 0], 2),
|
||||
b'\'' => ([b'\\', b'\'', 0, 0], 2),
|
||||
b'"' => ([b'\\', b'"', 0, 0], 2),
|
||||
b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1),
|
||||
_ => {
|
||||
let hi = HEX_DIGITS[usize::from(byte >> 4)];
|
||||
let lo = HEX_DIGITS[usize::from(byte & 0xf)];
|
||||
([b'\\', b'x', hi, lo], 4)
|
||||
}
|
||||
};
|
||||
*output = data;
|
||||
0..(len as u8)
|
||||
}
|
||||
|
||||
/// Escapes a character into provided buffer using `\u{NNNN}` representation.
|
||||
pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> {
|
||||
output[9] = b'}';
|
||||
|
||||
let ch = ch as u32;
|
||||
output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
|
||||
output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize];
|
||||
output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize];
|
||||
output[6] = HEX_DIGITS[((ch >> 8) & 15) as usize];
|
||||
output[7] = HEX_DIGITS[((ch >> 4) & 15) as usize];
|
||||
output[8] = HEX_DIGITS[((ch >> 0) & 15) as usize];
|
||||
|
||||
// or-ing 1 ensures that for ch==0 the code computes that one digit should
|
||||
// be printed.
|
||||
let start = (ch | 1).leading_zeros() as usize / 4 - 2;
|
||||
output[start..start + 3].copy_from_slice(b"\\u{");
|
||||
|
||||
(start as u8)..10
|
||||
}
|
||||
|
||||
/// An iterator over an fixed-size array.
|
||||
///
|
||||
/// This is essentially equivalent to array’s IntoIter except that indexes are
|
||||
/// limited to u8 to reduce size of the structure.
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct EscapeIterInner<const N: usize> {
|
||||
// Invariant: data[alive] is all ASCII.
|
||||
pub(crate) data: [u8; N],
|
||||
|
||||
// Invariant: alive.start <= alive.end <= N.
|
||||
pub(crate) alive: Range<u8>,
|
||||
}
|
||||
|
||||
impl<const N: usize> EscapeIterInner<N> {
|
||||
pub fn new(data: [u8; N], alive: Range<u8>) -> Self {
|
||||
const { assert!(N < 256) };
|
||||
debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
|
||||
let this = Self { data, alive };
|
||||
debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes());
|
||||
this
|
||||
}
|
||||
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
&self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
// SAFETY: self.data[self.alive] is all ASCII characters.
|
||||
unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) }
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
usize::from(self.alive.end - self.alive.start)
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Option<u8> {
|
||||
self.alive.next().map(|i| self.data[usize::from(i)])
|
||||
}
|
||||
|
||||
pub fn next_back(&mut self) -> Option<u8> {
|
||||
self.alive.next_back().map(|i| self.data[usize::from(i)])
|
||||
}
|
||||
|
||||
pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.alive.advance_by(n)
|
||||
}
|
||||
|
||||
pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.alive.advance_back_by(n)
|
||||
}
|
||||
}
|
@ -162,6 +162,7 @@
|
||||
#![feature(const_waker)]
|
||||
#![feature(core_panic)]
|
||||
#![feature(duration_consts_float)]
|
||||
#![feature(internal_impls_macro)]
|
||||
#![feature(ip)]
|
||||
#![feature(is_ascii_octdigit)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
@ -376,6 +377,7 @@ pub mod alloc;
|
||||
|
||||
// note: does not need to be public
|
||||
mod bool;
|
||||
mod escape;
|
||||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
|
@ -12,6 +12,60 @@ use crate::fmt::Debug;
|
||||
use crate::hash::Hash;
|
||||
use crate::hash::Hasher;
|
||||
|
||||
/// Implements a given marker trait for multiple types at the same time.
|
||||
///
|
||||
/// The basic syntax looks like this:
|
||||
/// ```ignore private macro
|
||||
/// marker_impls! { MarkerTrait for u8, i8 }
|
||||
/// ```
|
||||
/// You can also implement `unsafe` traits
|
||||
/// ```ignore private macro
|
||||
/// marker_impls! { unsafe MarkerTrait for u8, i8 }
|
||||
/// ```
|
||||
/// Add attributes to all impls:
|
||||
/// ```ignore private macro
|
||||
/// marker_impls! {
|
||||
/// #[allow(lint)]
|
||||
/// #[unstable(feature = "marker_trait", issue = "none")]
|
||||
/// MarkerTrait for u8, i8
|
||||
/// }
|
||||
/// ```
|
||||
/// And use generics:
|
||||
/// ```ignore private macro
|
||||
/// marker_impls! {
|
||||
/// MarkerTrait for
|
||||
/// u8, i8,
|
||||
/// {T: ?Sized} *const T,
|
||||
/// {T: ?Sized} *mut T,
|
||||
/// {T: MarkerTrait} PhantomData<T>,
|
||||
/// u32,
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "internal_impls_macro", issue = "none")]
|
||||
macro marker_impls {
|
||||
( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
|
||||
// This inner macro is needed because... idk macros are weird.
|
||||
// It allows repeating `meta` on all impls.
|
||||
#[unstable(feature = "internal_impls_macro", issue = "none")]
|
||||
macro _impl {
|
||||
( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
|
||||
$(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
|
||||
}
|
||||
}
|
||||
$( _impl! { $({$($bounds)*})? $T } )+
|
||||
},
|
||||
( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
|
||||
#[unstable(feature = "internal_impls_macro", issue = "none")]
|
||||
macro _impl {
|
||||
( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
|
||||
$(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
|
||||
}
|
||||
}
|
||||
|
||||
$( _impl! { $({$($bounds)*})? $T } )+
|
||||
},
|
||||
}
|
||||
|
||||
/// Types that can be transferred across thread boundaries.
|
||||
///
|
||||
/// This trait is automatically implemented when the compiler determines it's
|
||||
@ -214,6 +268,20 @@ pub trait StructuralEq {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead
|
||||
marker_impls! {
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
StructuralEq for
|
||||
usize, u8, u16, u32, u64, u128,
|
||||
isize, i8, i16, i32, i64, i128,
|
||||
bool,
|
||||
char,
|
||||
str /* Technically requires `[u8]: StructuralEq` */,
|
||||
{T, const N: usize} [T; N],
|
||||
{T} [T],
|
||||
{T: ?Sized} &T,
|
||||
}
|
||||
|
||||
/// Types whose values can be duplicated simply by copying bits.
|
||||
///
|
||||
/// By default, variable bindings have 'move semantics.' In other
|
||||
@ -401,6 +469,30 @@ pub macro Copy($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
// Implementations of `Copy` for primitive types.
|
||||
//
|
||||
// Implementations that cannot be described in Rust
|
||||
// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
// in `rustc_trait_selection`.
|
||||
marker_impls! {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Copy for
|
||||
usize, u8, u16, u32, u64, u128,
|
||||
isize, i8, i16, i32, i64, i128,
|
||||
f32, f64,
|
||||
bool, char,
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl Copy for ! {}
|
||||
|
||||
/// Shared references can be copied, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
|
||||
/// Types for which it is safe to share references between threads.
|
||||
///
|
||||
/// This trait is automatically implemented when the compiler determines
|
||||
@ -778,11 +870,14 @@ pub trait DiscriminantKind {
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
|
||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
||||
marker_impls! {
|
||||
unsafe Freeze for
|
||||
{T: ?Sized} PhantomData<T>,
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
{T: ?Sized} &T,
|
||||
{T: ?Sized} &mut T,
|
||||
}
|
||||
|
||||
/// Types that can be safely moved after being pinned.
|
||||
///
|
||||
@ -843,17 +938,19 @@ pub struct PhantomPinned;
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl !Unpin for PhantomPinned {}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<'a, T: ?Sized + 'a> Unpin for &'a T {}
|
||||
marker_impls! {
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
Unpin for
|
||||
{T: ?Sized} &T,
|
||||
{T: ?Sized} &mut T,
|
||||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {}
|
||||
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
impl<T: ?Sized> Unpin for *const T {}
|
||||
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
impl<T: ?Sized> Unpin for *mut T {}
|
||||
marker_impls! {
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
Unpin for
|
||||
{T: ?Sized} *const T,
|
||||
{T: ?Sized} *mut T,
|
||||
}
|
||||
|
||||
/// A marker for types that can be dropped.
|
||||
///
|
||||
@ -888,43 +985,25 @@ pub trait Tuple {}
|
||||
)]
|
||||
pub trait PointerLike {}
|
||||
|
||||
/// Implementations of `Copy` for primitive types.
|
||||
///
|
||||
/// Implementations that cannot be described in Rust
|
||||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
/// in `rustc_trait_selection`.
|
||||
mod copy_impls {
|
||||
/// A marker for types which can be used as types of `const` generic parameters.
|
||||
#[cfg_attr(not(bootstrap), lang = "const_param_ty")]
|
||||
#[unstable(feature = "adt_const_params", issue = "95174")]
|
||||
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
|
||||
pub trait ConstParamTy: StructuralEq {}
|
||||
|
||||
use super::Copy;
|
||||
|
||||
macro_rules! impl_copy {
|
||||
($($t:ty)*) => {
|
||||
$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Copy for $t {}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_copy! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
bool char
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl Copy for ! {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
/// Shared references can be copied, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
// FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure`
|
||||
// FIXME(generic_const_parameter_types): handle `ty::Tuple`
|
||||
marker_impls! {
|
||||
#[unstable(feature = "adt_const_params", issue = "95174")]
|
||||
ConstParamTy for
|
||||
usize, u8, u16, u32, u64, u128,
|
||||
isize, i8, i16, i32, i64, i128,
|
||||
bool,
|
||||
char,
|
||||
str /* Technically requires `[u8]: ConstParamTy` */,
|
||||
{T: ConstParamTy, const N: usize} [T; N],
|
||||
{T: ConstParamTy} [T],
|
||||
{T: ?Sized + ConstParamTy} &T,
|
||||
}
|
||||
|
||||
/// A common trait implemented by all function pointers.
|
||||
|
@ -1,4 +1,5 @@
|
||||
#[test]
|
||||
#[cfg_attr(not(bootstrap), allow(suspicious_double_ref_op))]
|
||||
fn test_borrowed_clone() {
|
||||
let x = 5;
|
||||
let y: &i32 = &x;
|
||||
|
@ -6,7 +6,7 @@ cfg_if::cfg_if! {
|
||||
mod static_local;
|
||||
#[doc(hidden)]
|
||||
pub use static_local::{Key, thread_local_inner};
|
||||
} else if #[cfg(all(target_thread_local))] {
|
||||
} else if #[cfg(target_thread_local)] {
|
||||
#[doc(hidden)]
|
||||
mod fast_local;
|
||||
#[doc(hidden)]
|
||||
|
@ -1,27 +0,0 @@
|
||||
# `debugger_visualizer`
|
||||
|
||||
The tracking issue for this feature is: [#95939]
|
||||
|
||||
[#95939]: https://github.com/rust-lang/rust/issues/95939
|
||||
|
||||
------------------------
|
||||
|
||||
The `debugger_visualizer` attribute can be used to instruct the compiler
|
||||
to embed a debugger visualizer file into the PDB/ELF generated by `rustc`.
|
||||
|
||||
## Examples
|
||||
|
||||
``` rust,ignore (partial-example)
|
||||
#![feature(debugger_visualizer)]
|
||||
#![debugger_visualizer(natvis_file = "foo.natvis")]
|
||||
#![debugger_visualizer(gdb_script_file = "foo.py")]
|
||||
struct Foo {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
Currently, this feature only supports embedding Natvis files on `-windows-msvc`
|
||||
targets via the `natvis_file` meta item. `-windows-gnu` targets are not currently
|
||||
supported.
|
@ -167,7 +167,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
|
||||
display_fn(move |f| {
|
||||
let mut bounds_dup = FxHashSet::default();
|
||||
|
||||
for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.clone())).enumerate() {
|
||||
for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(*b)).enumerate() {
|
||||
if i > 0 {
|
||||
f.write_str(" + ")?;
|
||||
}
|
||||
|
@ -313,7 +313,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::methods::CHARS_NEXT_CMP_INFO,
|
||||
crate::methods::CLEAR_WITH_DRAIN_INFO,
|
||||
crate::methods::CLONED_INSTEAD_OF_COPIED_INFO,
|
||||
crate::methods::CLONE_DOUBLE_REF_INFO,
|
||||
crate::methods::CLONE_ON_COPY_INFO,
|
||||
crate::methods::CLONE_ON_REF_PTR_INFO,
|
||||
crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
|
||||
|
@ -1,7 +1,6 @@
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::get_parent_node;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::ty::is_copy;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
||||
@ -9,7 +8,6 @@ use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use super::CLONE_DOUBLE_REF;
|
||||
use super::CLONE_ON_COPY;
|
||||
|
||||
/// Checks for the `CLONE_ON_COPY` lint.
|
||||
@ -42,41 +40,7 @@ pub(super) fn check(
|
||||
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
if let ty::Ref(_, inner, _) = arg_ty.kind() {
|
||||
if let ty::Ref(_, innermost, _) = inner.kind() {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
CLONE_DOUBLE_REF,
|
||||
expr.span,
|
||||
&with_forced_trimmed_paths!(format!(
|
||||
"using `clone` on a double-reference; \
|
||||
this will copy the reference of type `{ty}` instead of cloning the inner type"
|
||||
)),
|
||||
|diag| {
|
||||
if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let mut ty = innermost;
|
||||
let mut n = 0;
|
||||
while let ty::Ref(_, inner, _) = ty.kind() {
|
||||
ty = inner;
|
||||
n += 1;
|
||||
}
|
||||
let refs = "&".repeat(n + 1);
|
||||
let derefs = "*".repeat(n);
|
||||
let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
"try dereferencing it",
|
||||
with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
"or try being explicit if you are sure, that you want to clone a reference",
|
||||
explicit,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
if let ty::Ref(..) = inner.kind() {
|
||||
return; // don't report clone_on_copy
|
||||
}
|
||||
}
|
||||
|
@ -984,29 +984,6 @@ declare_clippy_lint! {
|
||||
"using 'clone' on a ref-counted pointer"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for usage of `.clone()` on an `&&T`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Cloning an `&&T` copies the inner `&T`, instead of
|
||||
/// cloning the underlying `T`.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// fn main() {
|
||||
/// let x = vec![1];
|
||||
/// let y = &&x;
|
||||
/// let z = y.clone();
|
||||
/// println!("{:p} {:p}", *y, z); // prints out the same pointer
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub CLONE_DOUBLE_REF,
|
||||
correctness,
|
||||
"using `clone` on `&&T`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for usage of `.to_string()` on an `&&T` where
|
||||
@ -3258,7 +3235,6 @@ impl_lint_pass!(Methods => [
|
||||
CHARS_LAST_CMP,
|
||||
CLONE_ON_COPY,
|
||||
CLONE_ON_REF_PTR,
|
||||
CLONE_DOUBLE_REF,
|
||||
COLLAPSIBLE_STR_REPLACE,
|
||||
ITER_OVEREAGER_CLONED,
|
||||
CLONED_INSTEAD_OF_COPIED,
|
||||
|
@ -30,6 +30,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
||||
("clippy::stutter", "clippy::module_name_repetitions"),
|
||||
("clippy::to_string_in_display", "clippy::recursive_format_impl"),
|
||||
("clippy::zero_width_space", "clippy::invisible_characters"),
|
||||
("clippy::clone_double_ref", "suspicious_double_ref_op"),
|
||||
("clippy::drop_bounds", "drop_bounds"),
|
||||
("clippy::for_loop_over_option", "for_loops_over_fallibles"),
|
||||
("clippy::for_loop_over_result", "for_loops_over_fallibles"),
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(
|
||||
clippy::borrow_deref_ref,
|
||||
clippy::clone_double_ref,
|
||||
suspicious_double_ref_op,
|
||||
clippy::explicit_auto_deref,
|
||||
clippy::needless_borrow,
|
||||
clippy::uninlined_format_args
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![allow(unused_variables)]
|
||||
#![allow(
|
||||
clippy::borrow_deref_ref,
|
||||
clippy::clone_double_ref,
|
||||
suspicious_double_ref_op,
|
||||
clippy::explicit_auto_deref,
|
||||
clippy::needless_borrow,
|
||||
clippy::uninlined_format_args
|
||||
|
@ -36,6 +36,7 @@
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
@ -67,6 +68,7 @@
|
||||
#![warn(clippy::module_name_repetitions)]
|
||||
#![warn(clippy::recursive_format_impl)]
|
||||
#![warn(clippy::invisible_characters)]
|
||||
#![warn(suspicious_double_ref_op)]
|
||||
#![warn(drop_bounds)]
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
|
@ -36,6 +36,7 @@
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
@ -67,6 +68,7 @@
|
||||
#![warn(clippy::stutter)]
|
||||
#![warn(clippy::to_string_in_display)]
|
||||
#![warn(clippy::zero_width_space)]
|
||||
#![warn(clippy::clone_double_ref)]
|
||||
#![warn(clippy::drop_bounds)]
|
||||
#![warn(clippy::for_loop_over_option)]
|
||||
#![warn(clippy::for_loop_over_result)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
|
||||
--> $DIR/rename.rs:42:9
|
||||
--> $DIR/rename.rs:43:9
|
||||
|
|
||||
LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
||||
@ -7,250 +7,256 @@ LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||
--> $DIR/rename.rs:43:9
|
||||
--> $DIR/rename.rs:44:9
|
||||
|
|
||||
LL | #![warn(clippy::blacklisted_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:44:9
|
||||
--> $DIR/rename.rs:45:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:45:9
|
||||
--> $DIR/rename.rs:46:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
||||
--> $DIR/rename.rs:46:9
|
||||
--> $DIR/rename.rs:47:9
|
||||
|
|
||||
LL | #![warn(clippy::box_vec)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||
|
||||
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
||||
--> $DIR/rename.rs:47:9
|
||||
--> $DIR/rename.rs:48:9
|
||||
|
|
||||
LL | #![warn(clippy::const_static_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||
|
||||
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
||||
--> $DIR/rename.rs:48:9
|
||||
--> $DIR/rename.rs:49:9
|
||||
|
|
||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||
|
||||
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
|
||||
--> $DIR/rename.rs:49:9
|
||||
--> $DIR/rename.rs:50:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||
--> $DIR/rename.rs:50:9
|
||||
--> $DIR/rename.rs:51:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_method)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||
|
||||
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
||||
--> $DIR/rename.rs:51:9
|
||||
--> $DIR/rename.rs:52:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_type)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||
|
||||
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:53:9
|
||||
|
|
||||
LL | #![warn(clippy::eval_order_dependence)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||
--> $DIR/rename.rs:53:9
|
||||
--> $DIR/rename.rs:54:9
|
||||
|
|
||||
LL | #![warn(clippy::identity_conversion)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||
|
||||
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
||||
--> $DIR/rename.rs:54:9
|
||||
--> $DIR/rename.rs:55:9
|
||||
|
|
||||
LL | #![warn(clippy::if_let_some_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||
--> $DIR/rename.rs:55:9
|
||||
--> $DIR/rename.rs:56:9
|
||||
|
|
||||
LL | #![warn(clippy::logic_bug)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
||||
|
||||
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
||||
--> $DIR/rename.rs:56:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::new_without_default_derive)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
||||
|
||||
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
||||
--> $DIR/rename.rs:57:9
|
||||
--> $DIR/rename.rs:58:9
|
||||
|
|
||||
LL | #![warn(clippy::option_and_then_some)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||
|
||||
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:58:9
|
||||
--> $DIR/rename.rs:59:9
|
||||
|
|
||||
LL | #![warn(clippy::option_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:59:9
|
||||
--> $DIR/rename.rs:60:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:60:9
|
||||
--> $DIR/rename.rs:61:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:61:9
|
||||
--> $DIR/rename.rs:62:9
|
||||
|
|
||||
LL | #![warn(clippy::option_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
||||
--> $DIR/rename.rs:62:9
|
||||
--> $DIR/rename.rs:63:9
|
||||
|
|
||||
LL | #![warn(clippy::ref_in_deref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||
|
||||
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:63:9
|
||||
--> $DIR/rename.rs:64:9
|
||||
|
|
||||
LL | #![warn(clippy::result_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:65:9
|
||||
|
|
||||
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:66:9
|
||||
|
|
||||
LL | #![warn(clippy::result_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
||||
--> $DIR/rename.rs:66:9
|
||||
--> $DIR/rename.rs:67:9
|
||||
|
|
||||
LL | #![warn(clippy::single_char_push_str)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||
|
||||
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
||||
--> $DIR/rename.rs:67:9
|
||||
--> $DIR/rename.rs:68:9
|
||||
|
|
||||
LL | #![warn(clippy::stutter)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||
|
||||
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
||||
--> $DIR/rename.rs:68:9
|
||||
--> $DIR/rename.rs:69:9
|
||||
|
|
||||
LL | #![warn(clippy::to_string_in_display)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||
|
||||
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
||||
--> $DIR/rename.rs:69:9
|
||||
--> $DIR/rename.rs:70:9
|
||||
|
|
||||
LL | #![warn(clippy::zero_width_space)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
|
||||
--> $DIR/rename.rs:71:9
|
||||
|
|
||||
LL | #![warn(clippy::clone_double_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
|
||||
|
||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||
--> $DIR/rename.rs:70:9
|
||||
--> $DIR/rename.rs:72:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:71:9
|
||||
--> $DIR/rename.rs:73:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:72:9
|
||||
--> $DIR/rename.rs:74:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:73:9
|
||||
--> $DIR/rename.rs:75:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:74:9
|
||||
--> $DIR/rename.rs:76:9
|
||||
|
|
||||
LL | #![warn(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||
|
||||
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
||||
--> $DIR/rename.rs:75:9
|
||||
--> $DIR/rename.rs:77:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_atomic_ordering)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||
|
||||
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
||||
--> $DIR/rename.rs:76:9
|
||||
--> $DIR/rename.rs:78:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||
|
||||
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
|
||||
--> $DIR/rename.rs:77:9
|
||||
--> $DIR/rename.rs:79:9
|
||||
|
|
||||
LL | #![warn(clippy::let_underscore_drop)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
|
||||
|
||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||
--> $DIR/rename.rs:78:9
|
||||
--> $DIR/rename.rs:80:9
|
||||
|
|
||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||
|
||||
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
||||
--> $DIR/rename.rs:79:9
|
||||
--> $DIR/rename.rs:81:9
|
||||
|
|
||||
LL | #![warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||
--> $DIR/rename.rs:80:9
|
||||
--> $DIR/rename.rs:82:9
|
||||
|
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
--> $DIR/rename.rs:81:9
|
||||
--> $DIR/rename.rs:83:9
|
||||
|
|
||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
|
||||
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
||||
--> $DIR/rename.rs:82:9
|
||||
--> $DIR/rename.rs:84:9
|
||||
|
|
||||
LL | #![warn(clippy::unknown_clippy_lints)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||
|
||||
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
||||
--> $DIR/rename.rs:83:9
|
||||
--> $DIR/rename.rs:85:9
|
||||
|
|
||||
LL | #![warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
||||
error: aborting due to 42 previous errors
|
||||
error: aborting due to 43 previous errors
|
||||
|
||||
|
@ -42,14 +42,6 @@ fn clone_on_copy_generic<T: Copy>(t: T) {
|
||||
Some(t).clone();
|
||||
}
|
||||
|
||||
fn clone_on_double_ref() {
|
||||
let x = vec![1];
|
||||
let y = &&x;
|
||||
let z: &Vec<_> = y.clone();
|
||||
|
||||
println!("{:p} {:p}", *y, z);
|
||||
}
|
||||
|
||||
mod many_derefs {
|
||||
struct A;
|
||||
struct B;
|
||||
@ -84,11 +76,6 @@ mod many_derefs {
|
||||
let _: E = a.clone();
|
||||
let _: E = *****a;
|
||||
}
|
||||
|
||||
fn check(mut encoded: &[u8]) {
|
||||
let _ = &mut encoded.clone();
|
||||
let _ = &encoded.clone();
|
||||
}
|
||||
}
|
||||
|
||||
mod issue2076 {
|
||||
|
@ -44,63 +44,17 @@ error: using `clone` on type `Option<T>` which implements the `Copy` trait
|
||||
LL | Some(t).clone();
|
||||
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
|
||||
|
||||
error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
|
||||
--> $DIR/unnecessary_clone.rs:48:22
|
||||
|
|
||||
LL | let z: &Vec<_> = y.clone();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[deny(clippy::clone_double_ref)]` on by default
|
||||
help: try dereferencing it
|
||||
|
|
||||
LL | let z: &Vec<_> = &(*y).clone();
|
||||
| ~~~~~~~~~~~~~
|
||||
help: or try being explicit if you are sure, that you want to clone a reference
|
||||
|
|
||||
LL | let z: &Vec<_> = <&Vec<i32>>::clone(y);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: using `clone` on type `E` which implements the `Copy` trait
|
||||
--> $DIR/unnecessary_clone.rs:84:20
|
||||
--> $DIR/unnecessary_clone.rs:76:20
|
||||
|
|
||||
LL | let _: E = a.clone();
|
||||
| ^^^^^^^^^ help: try dereferencing it: `*****a`
|
||||
|
||||
error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
|
||||
--> $DIR/unnecessary_clone.rs:89:22
|
||||
|
|
||||
LL | let _ = &mut encoded.clone();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try dereferencing it
|
||||
|
|
||||
LL | let _ = &mut &(*encoded).clone();
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
help: or try being explicit if you are sure, that you want to clone a reference
|
||||
|
|
||||
LL | let _ = &mut <&[u8]>::clone(encoded);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
|
||||
--> $DIR/unnecessary_clone.rs:90:18
|
||||
|
|
||||
LL | let _ = &encoded.clone();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try dereferencing it
|
||||
|
|
||||
LL | let _ = &&(*encoded).clone();
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
help: or try being explicit if you are sure, that you want to clone a reference
|
||||
|
|
||||
LL | let _ = &<&[u8]>::clone(encoded);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: using `.clone()` on a ref-counted pointer
|
||||
--> $DIR/unnecessary_clone.rs:108:14
|
||||
--> $DIR/unnecessary_clone.rs:95:14
|
||||
|
|
||||
LL | Some(try_opt!(Some(rc)).clone())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::<u8>::clone(&try_opt!(Some(rc)))`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
@ -1385,7 +1385,9 @@ impl<'test> TestCx<'test> {
|
||||
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
|
||||
let mut unexpected = Vec::new();
|
||||
let mut found = vec![false; expected_errors.len()];
|
||||
for actual_error in &actual_errors {
|
||||
for mut actual_error in actual_errors {
|
||||
actual_error.msg = self.normalize_output(&actual_error.msg, &[]);
|
||||
|
||||
let opt_index =
|
||||
expected_errors.iter().enumerate().position(|(index, expected_error)| {
|
||||
!found[index]
|
||||
@ -1404,7 +1406,8 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
None => {
|
||||
// If the test is a known bug, don't require that the error is annotated
|
||||
if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
|
||||
if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note)
|
||||
{
|
||||
self.error(&format!(
|
||||
"{}:{}: unexpected {}: '{}'",
|
||||
file_name,
|
||||
|
@ -2,7 +2,6 @@
|
||||
// ignore-lldb
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![feature(debugger_visualizer)]
|
||||
#![debugger_visualizer(natvis_file = "dependency-with-embedded-visualizers.natvis")]
|
||||
#![debugger_visualizer(gdb_script_file = "dependency-with-embedded-visualizers.py")]
|
||||
#![crate_type = "rlib"]
|
||||
|
@ -60,7 +60,6 @@
|
||||
// gdb-check:$4 = "Person A" is 10 years old.
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![feature(debugger_visualizer)]
|
||||
#![debugger_visualizer(natvis_file = "embedded-visualizer.natvis")]
|
||||
#![debugger_visualizer(gdb_script_file = "embedded-visualizer.py")]
|
||||
|
||||
|
@ -19,6 +19,8 @@ pub trait SVec: Index<
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
Output = <Index<<Self as SVec>::Item,
|
||||
//~^ expected 1 lifetime argument
|
||||
//~| expected 1 generic argument
|
||||
@ -26,6 +28,8 @@ pub trait SVec: Index<
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
//~^ expected 1 lifetime argument
|
||||
//~| expected 1 generic argument
|
||||
@ -34,11 +38,15 @@ pub trait SVec: Index<
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| expected 1 generic argument
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
//~| missing generics for associated type `SVec::Item`
|
||||
> {
|
||||
type Item<'a, T>;
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -21,7 +21,7 @@ LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -31,13 +31,13 @@ LL | <Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:22:37
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -47,13 +47,13 @@ LL | Output = <Index<<Self as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:22:37
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -63,13 +63,13 @@ LL | Output = <Index<<Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:30
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -79,13 +79,13 @@ LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:30
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -95,13 +95,13 @@ LL | Output = <Self as SVec>::Item<T>> as SVec>::Item,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:46
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -111,13 +111,13 @@ LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:46
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -133,7 +133,7 @@ LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -149,7 +149,7 @@ LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -165,7 +165,7 @@ LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -181,7 +181,7 @@ LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -191,13 +191,13 @@ LL | <Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:22:37
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -207,13 +207,13 @@ LL | Output = <Index<<Self as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:22:37
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -223,13 +223,13 @@ LL | Output = <Index<<Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:30
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -239,13 +239,13 @@ LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:30
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -255,13 +255,13 @@ LL | Output = <Self as SVec>::Item<T>> as SVec>::Item,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:46
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -271,13 +271,13 @@ LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:29:46
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -317,13 +317,141 @@ LL | | > {
|
||||
| |__^ ...because it uses `Self` as a type parameter
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:45:38
|
||||
--> $DIR/issue-105742.rs:15:21
|
||||
|
|
||||
LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
help: add missing lifetime argument
|
||||
|
|
||||
LL | <Self as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:15:21
|
||||
|
|
||||
LL | <Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | <Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
help: add missing lifetime argument
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:24:37
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | Output = <Index<<Self as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
help: add missing lifetime argument
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:33:30
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item<T>> as SVec>::Item,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
help: add missing lifetime argument
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>,
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:33:46
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item,
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | Output = <Self as SVec>::Item> as SVec>::Item<T>,
|
||||
| +++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:53:38
|
||||
|
|
||||
LL | fn len(&self) -> <Self as SVec>::Item;
|
||||
| ^^^^ expected 1 lifetime argument
|
||||
|
|
||||
note: associated type defined here, with 1 lifetime parameter: `'a`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ --
|
||||
@ -333,13 +461,13 @@ LL | fn len(&self) -> <Self as SVec>::Item<'_>;
|
||||
| ++++
|
||||
|
||||
error[E0107]: missing generics for associated type `SVec::Item`
|
||||
--> $DIR/issue-105742.rs:45:38
|
||||
--> $DIR/issue-105742.rs:53:38
|
||||
|
|
||||
LL | fn len(&self) -> <Self as SVec>::Item;
|
||||
| ^^^^ expected 1 generic argument
|
||||
|
|
||||
note: associated type defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/issue-105742.rs:43:10
|
||||
--> $DIR/issue-105742.rs:51:10
|
||||
|
|
||||
LL | type Item<'a, T>;
|
||||
| ^^^^ -
|
||||
@ -348,7 +476,7 @@ help: add missing generic argument
|
||||
LL | fn len(&self) -> <Self as SVec>::Item<T>;
|
||||
| +++
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0107.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
@ -193,10 +193,13 @@ trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
|
||||
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
trait TRS1: Iterator<Item: Copy, Item: Send> {}
|
||||
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
trait TRS2: Iterator<Item: Copy, Item: Copy> {}
|
||||
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
trait TRS3: Iterator<Item: 'static, Item: 'static> {}
|
||||
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
|
||||
trait TRW1<T>
|
||||
where
|
||||
T: Iterator<Item: Copy, Item: Send>,
|
||||
|
@ -367,7 +367,15 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:196:34
|
||||
--> $DIR/duplicate.rs:194:34
|
||||
|
|
||||
LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:197:34
|
||||
|
|
||||
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -375,7 +383,15 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:198:37
|
||||
--> $DIR/duplicate.rs:197:34
|
||||
|
|
||||
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:200:37
|
||||
|
|
||||
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
@ -383,7 +399,15 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:202:29
|
||||
--> $DIR/duplicate.rs:200:37
|
||||
|
|
||||
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:205:29
|
||||
|
|
||||
LL | T: Iterator<Item: Copy, Item: Send>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -391,7 +415,7 @@ LL | T: Iterator<Item: Copy, Item: Send>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:208:29
|
||||
--> $DIR/duplicate.rs:211:29
|
||||
|
|
||||
LL | T: Iterator<Item: Copy, Item: Copy>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -399,7 +423,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:214:32
|
||||
--> $DIR/duplicate.rs:217:32
|
||||
|
|
||||
LL | T: Iterator<Item: 'static, Item: 'static>,
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
@ -407,7 +431,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:220:32
|
||||
--> $DIR/duplicate.rs:223:32
|
||||
|
|
||||
LL | Self: Iterator<Item: Copy, Item: Send>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -415,7 +439,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:220:32
|
||||
--> $DIR/duplicate.rs:223:32
|
||||
|
|
||||
LL | Self: Iterator<Item: Copy, Item: Send>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -423,7 +447,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:227:32
|
||||
--> $DIR/duplicate.rs:230:32
|
||||
|
|
||||
LL | Self: Iterator<Item: Copy, Item: Copy>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -431,7 +455,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:227:32
|
||||
--> $DIR/duplicate.rs:230:32
|
||||
|
|
||||
LL | Self: Iterator<Item: Copy, Item: Copy>,
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -439,7 +463,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:234:35
|
||||
--> $DIR/duplicate.rs:237:35
|
||||
|
|
||||
LL | Self: Iterator<Item: 'static, Item: 'static>,
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
@ -447,7 +471,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:234:35
|
||||
--> $DIR/duplicate.rs:237:35
|
||||
|
|
||||
LL | Self: Iterator<Item: 'static, Item: 'static>,
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
@ -455,7 +479,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:252:40
|
||||
--> $DIR/duplicate.rs:255:40
|
||||
|
|
||||
LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -463,7 +487,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:254:44
|
||||
--> $DIR/duplicate.rs:257:44
|
||||
|
|
||||
LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -471,7 +495,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:256:43
|
||||
--> $DIR/duplicate.rs:259:43
|
||||
|
|
||||
LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
@ -479,7 +503,7 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:240:34
|
||||
--> $DIR/duplicate.rs:243:34
|
||||
|
|
||||
LL | type A: Iterator<Item: Copy, Item: Send>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -487,7 +511,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:244:34
|
||||
--> $DIR/duplicate.rs:247:34
|
||||
|
|
||||
LL | type A: Iterator<Item: Copy, Item: Copy>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
@ -495,13 +519,13 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/duplicate.rs:248:37
|
||||
--> $DIR/duplicate.rs:251:37
|
||||
|
|
||||
LL | type A: Iterator<Item: 'static, Item: 'static>;
|
||||
| ------------- ^^^^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error: aborting due to 63 previous errors
|
||||
error: aborting due to 66 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0719`.
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#![feature(return_type_notation, async_fn_in_trait)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
//~| WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait Trait {
|
||||
async fn method() {}
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: return type notation uses `()` instead of `(..)` for elided arguments
|
||||
--> $DIR/bad-inputs-and-output.rs:19:24
|
||||
--> $DIR/bad-inputs-and-output.rs:18:24
|
||||
|
|
||||
LL | fn baz<T: Trait<method(..): Send>>() {}
|
||||
| ^^ help: remove the `..`
|
||||
|
||||
error[E0658]: associated type bounds are unstable
|
||||
--> $DIR/bad-inputs-and-output.rs:11:17
|
||||
--> $DIR/bad-inputs-and-output.rs:10:17
|
||||
|
|
||||
LL | fn foo<T: Trait<method(i32): Send>>() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -14,7 +14,7 @@ LL | fn foo<T: Trait<method(i32): Send>>() {}
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: associated type bounds are unstable
|
||||
--> $DIR/bad-inputs-and-output.rs:15:17
|
||||
--> $DIR/bad-inputs-and-output.rs:14:17
|
||||
|
|
||||
LL | fn bar<T: Trait<method() -> (): Send>>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -31,26 +31,18 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/bad-inputs-and-output.rs:3:34
|
||||
|
|
||||
LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: argument types not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:11:23
|
||||
--> $DIR/bad-inputs-and-output.rs:10:23
|
||||
|
|
||||
LL | fn foo<T: Trait<method(i32): Send>>() {}
|
||||
| ^^^^^ help: remove the input types: `()`
|
||||
|
||||
error: return type not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:15:25
|
||||
--> $DIR/bad-inputs-and-output.rs:14:25
|
||||
|
|
||||
LL | fn bar<T: Trait<method() -> (): Send>>() {}
|
||||
| ^^^^^^ help: remove the return type
|
||||
|
||||
error: aborting due to 5 previous errors; 2 warnings emitted
|
||||
error: aborting due to 5 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#![feature(return_type_notation, async_fn_in_trait)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
//~| WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait Foo {
|
||||
async fn method() -> Result<(), ()>;
|
||||
|
@ -7,13 +7,5 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/basic.rs:5:34
|
||||
|
|
||||
LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
warning: 2 warnings emitted
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -7,31 +7,23 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/basic.rs:5:34
|
||||
|
|
||||
LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
--> $DIR/basic.rs:24:13
|
||||
--> $DIR/basic.rs:23:13
|
||||
|
|
||||
LL | is_send(foo::<T>());
|
||||
| ^^^^^^^^^^ future returned by `foo` is not `Send`
|
||||
|
|
||||
= help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
|
||||
note: future is not `Send` as it awaits another future which is not `Send`
|
||||
--> $DIR/basic.rs:14:5
|
||||
--> $DIR/basic.rs:13:5
|
||||
|
|
||||
LL | T::method().await?;
|
||||
| ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send`
|
||||
note: required by a bound in `is_send`
|
||||
--> $DIR/basic.rs:18:20
|
||||
--> $DIR/basic.rs:17:20
|
||||
|
|
||||
LL | fn is_send(_: impl Send) {}
|
||||
| ^^^^ required by this bound in `is_send`
|
||||
|
||||
error: aborting due to previous error; 2 warnings emitted
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#![feature(return_type_notation, async_fn_in_trait)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
//~| WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
@ -7,19 +7,11 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/equality.rs:3:34
|
||||
|
|
||||
LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: return type notation is not allowed to use type equality
|
||||
--> $DIR/equality.rs:13:18
|
||||
--> $DIR/equality.rs:12:18
|
||||
|
|
||||
LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 2 warnings emitted
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#![feature(return_type_notation, async_fn_in_trait)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
//~| WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait Trait {
|
||||
async fn method() {}
|
||||
|
@ -7,19 +7,11 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/missing.rs:3:34
|
||||
|
|
||||
LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: cannot find associated function `methid` in trait `Trait`
|
||||
--> $DIR/missing.rs:11:17
|
||||
--> $DIR/missing.rs:10:17
|
||||
|
|
||||
LL | fn bar<T: Trait<methid(): Send>>() {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 2 warnings emitted
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
26
tests/ui/associated-type-bounds/supertrait-defines-ty.rs
Normal file
26
tests/ui/associated-type-bounds/supertrait-defines-ty.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// check-pass
|
||||
|
||||
// Make sure that we don't look into associated type bounds when looking for
|
||||
// supertraits that define an associated type. Fixes #76593.
|
||||
|
||||
#![feature(associated_type_bounds)]
|
||||
|
||||
trait Load: Sized {
|
||||
type Blob;
|
||||
}
|
||||
|
||||
trait Primitive: Load<Blob = Self> {}
|
||||
|
||||
trait BlobPtr: Primitive {}
|
||||
|
||||
trait CleanPtr: Load<Blob: BlobPtr> {
|
||||
fn to_blob(&self) -> Self::Blob;
|
||||
}
|
||||
|
||||
impl Load for () {
|
||||
type Blob = Self;
|
||||
}
|
||||
impl Primitive for () {}
|
||||
impl BlobPtr for () {}
|
||||
|
||||
fn main() {}
|
@ -1,11 +0,0 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-default-fn-overridden.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -1,11 +0,0 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-default-fn-overridden.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -4,7 +4,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: expected identifier, found keyword `self`
|
||||
--> $DIR/bad-signatures.rs:9:23
|
||||
--> $DIR/bad-signatures.rs:8:23
|
||||
|
|
||||
LL | async fn bar(&abc self);
|
||||
| ^^^^ expected identifier, found keyword
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found keyword `self`
|
||||
--> $DIR/bad-signatures.rs:9:23
|
||||
--> $DIR/bad-signatures.rs:8:23
|
||||
|
|
||||
LL | async fn bar(&abc self);
|
||||
| -----^^^^
|
||||
@ -13,14 +13,5 @@ LL | async fn bar(&abc self);
|
||||
| | expected one of `:`, `@`, or `|`
|
||||
| help: declare the type after the parameter binding: `<identifier>: <type>`
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/bad-signatures.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: expected identifier, found keyword `self`
|
||||
--> $DIR/bad-signatures.rs:9:23
|
||||
--> $DIR/bad-signatures.rs:8:23
|
||||
|
|
||||
LL | async fn bar(&abc self);
|
||||
| ^^^^ expected identifier, found keyword
|
||||
|
||||
error: expected one of `:`, `@`, or `|`, found keyword `self`
|
||||
--> $DIR/bad-signatures.rs:9:23
|
||||
--> $DIR/bad-signatures.rs:8:23
|
||||
|
|
||||
LL | async fn bar(&abc self);
|
||||
| -----^^^^
|
||||
@ -13,14 +13,5 @@ LL | async fn bar(&abc self);
|
||||
| | expected one of `:`, `@`, or `|`
|
||||
| help: declare the type after the parameter binding: `<identifier>: <type>`
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/bad-signatures.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait MyTrait {
|
||||
async fn bar(&abc self);
|
||||
|
@ -1,12 +1,3 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: async associated function in trait cannot be specialized
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:16:5
|
||||
|
|
||||
@ -15,5 +6,5 @@ LL | default async fn foo(_: T) -> &'static str {
|
||||
|
|
||||
= note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,12 +1,3 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0053]: method `foo` has an incompatible type for trait
|
||||
--> $DIR/dont-project-to-specializable-projection.rs:16:35
|
||||
|
|
||||
@ -29,6 +20,6 @@ LL | default async fn foo(_: T) -> &'static str {
|
||||
|
|
||||
= note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
||||
|
@ -1,14 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/lifetime-mismatch.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
||||
--> $DIR/lifetime-mismatch.rs:14:17
|
||||
--> $DIR/lifetime-mismatch.rs:13:17
|
||||
|
|
||||
LL | async fn foo<'a>(&self);
|
||||
| ---- lifetimes in impl do not match this method in trait
|
||||
@ -16,6 +7,6 @@ LL | async fn foo<'a>(&self);
|
||||
LL | async fn foo(&self) {}
|
||||
| ^ lifetimes do not match method in trait
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0195`.
|
||||
|
@ -1,14 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/lifetime-mismatch.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
||||
--> $DIR/lifetime-mismatch.rs:14:17
|
||||
--> $DIR/lifetime-mismatch.rs:13:17
|
||||
|
|
||||
LL | async fn foo<'a>(&self);
|
||||
| ---- lifetimes in impl do not match this method in trait
|
||||
@ -16,6 +7,6 @@ LL | async fn foo<'a>(&self);
|
||||
LL | async fn foo(&self) {}
|
||||
| ^ lifetimes do not match method in trait
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0195`.
|
||||
|
@ -3,7 +3,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
|
||||
trait MyTrait {
|
||||
async fn foo<'a>(&self);
|
||||
|
@ -1,29 +1,20 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/missing-send-bound.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
--> $DIR/missing-send-bound.rs:17:20
|
||||
--> $DIR/missing-send-bound.rs:16:20
|
||||
|
|
||||
LL | assert_is_send(test::<T>());
|
||||
| ^^^^^^^^^^^ future returned by `test` is not `Send`
|
||||
|
|
||||
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
|
||||
note: future is not `Send` as it awaits another future which is not `Send`
|
||||
--> $DIR/missing-send-bound.rs:13:5
|
||||
--> $DIR/missing-send-bound.rs:12:5
|
||||
|
|
||||
LL | T::bar().await;
|
||||
| ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
|
||||
note: required by a bound in `assert_is_send`
|
||||
--> $DIR/missing-send-bound.rs:21:27
|
||||
--> $DIR/missing-send-bound.rs:20:27
|
||||
|
|
||||
LL | fn assert_is_send(_: impl Send) {}
|
||||
| ^^^^ required by this bound in `assert_is_send`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,29 +1,20 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/missing-send-bound.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
--> $DIR/missing-send-bound.rs:17:20
|
||||
--> $DIR/missing-send-bound.rs:16:20
|
||||
|
|
||||
LL | assert_is_send(test::<T>());
|
||||
| ^^^^^^^^^^^ future returned by `test` is not `Send`
|
||||
|
|
||||
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
|
||||
note: future is not `Send` as it awaits another future which is not `Send`
|
||||
--> $DIR/missing-send-bound.rs:13:5
|
||||
--> $DIR/missing-send-bound.rs:12:5
|
||||
|
|
||||
LL | T::bar().await;
|
||||
| ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
|
||||
note: required by a bound in `assert_is_send`
|
||||
--> $DIR/missing-send-bound.rs:21:27
|
||||
--> $DIR/missing-send-bound.rs:20:27
|
||||
|
|
||||
LL | fn assert_is_send(_: impl Send) {}
|
||||
| ^^^^ required by this bound in `assert_is_send`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
|
||||
trait Foo {
|
||||
async fn bar();
|
||||
|
@ -1,20 +1,11 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/object-safety.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/object-safety.rs:13:12
|
||||
--> $DIR/object-safety.rs:12:12
|
||||
|
|
||||
LL | let x: &dyn Foo = todo!();
|
||||
| ^^^^^^^^ `Foo` cannot be made into an object
|
||||
|
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/object-safety.rs:9:14
|
||||
--> $DIR/object-safety.rs:8:14
|
||||
|
|
||||
LL | trait Foo {
|
||||
| --- this trait cannot be made into an object...
|
||||
@ -22,6 +13,6 @@ LL | async fn foo(&self);
|
||||
| ^^^ ...because method `foo` is `async`
|
||||
= help: consider moving `foo` to another trait
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
@ -1,20 +1,11 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/object-safety.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/object-safety.rs:13:12
|
||||
--> $DIR/object-safety.rs:12:12
|
||||
|
|
||||
LL | let x: &dyn Foo = todo!();
|
||||
| ^^^^^^^^ `Foo` cannot be made into an object
|
||||
|
|
||||
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/object-safety.rs:9:14
|
||||
--> $DIR/object-safety.rs:8:14
|
||||
|
|
||||
LL | trait Foo {
|
||||
| --- this trait cannot be made into an object...
|
||||
@ -22,6 +13,6 @@ LL | async fn foo(&self);
|
||||
| ^^^ ...because method `foo` is `async`
|
||||
= help: consider moving `foo` to another trait
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
@ -3,7 +3,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
|
||||
trait Foo {
|
||||
async fn foo(&self);
|
||||
|
@ -1,14 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/return-type-suggestion.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/return-type-suggestion.rs:10:9
|
||||
--> $DIR/return-type-suggestion.rs:9:9
|
||||
|
|
||||
LL | Ok(())
|
||||
| ^^^^^^- help: consider using a semicolon here: `;`
|
||||
@ -18,6 +9,6 @@ LL | Ok(())
|
||||
= note: expected unit type `()`
|
||||
found enum `Result<(), _>`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,14 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/return-type-suggestion.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/return-type-suggestion.rs:10:9
|
||||
--> $DIR/return-type-suggestion.rs:9:9
|
||||
|
|
||||
LL | Ok(())
|
||||
| ^^^^^^- help: consider using a semicolon here: `;`
|
||||
@ -18,6 +9,6 @@ LL | Ok(())
|
||||
= note: expected unit type `()`
|
||||
found enum `Result<(), _>`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -3,7 +3,6 @@
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
|
||||
trait A {
|
||||
async fn e() {
|
||||
|
@ -7,14 +7,6 @@ LL | #![feature(return_type_notation)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-early.rs:5:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
error: higher-ranked lifetime error
|
||||
--> $DIR/issue-110963-early.rs:15:5
|
||||
|
|
||||
@ -41,5 +33,5 @@ LL | | });
|
||||
|
|
||||
= note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#![feature(return_type_notation)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait HealthCheck {
|
||||
async fn check(&mut self) -> bool;
|
||||
|
@ -7,13 +7,5 @@ LL | #![feature(return_type_notation)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-110963-late.rs:6:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
|
||||
warning: 2 warnings emitted
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
fn check(_: impl std::marker::ConstParamTy) {}
|
||||
|
||||
fn main() {
|
||||
check(main); //~ error: `fn() {main}` can't be used as a const parameter type
|
||||
check(|| {}); //~ error: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type
|
||||
check(main as fn()); //~ error: `fn()` can't be used as a const parameter type
|
||||
check(&mut ()); //~ error: `&mut ()` can't be used as a const parameter type
|
||||
check(&mut () as *mut ()); //~ error: `*mut ()` can't be used as a const parameter type
|
||||
check(&() as *const ()); //~ error: `*const ()` can't be used as a const parameter type
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
error[E0277]: `fn() {main}` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:7:11
|
||||
|
|
||||
LL | check(main);
|
||||
| ----- ^^^^ the trait `ConstParamTy` is not implemented for fn item `fn() {main}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:8:11
|
||||
|
|
||||
LL | check(|| {});
|
||||
| ----- ^^^^^ the trait `ConstParamTy` is not implemented for closure `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `fn()` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:9:11
|
||||
|
|
||||
LL | check(main as fn());
|
||||
| ----- ^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `fn()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `&mut ()` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:10:11
|
||||
|
|
||||
LL | check(&mut ());
|
||||
| ----- ^^^^^^^ the trait `ConstParamTy` is not implemented for `&mut ()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `*mut ()` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:11:11
|
||||
|
|
||||
LL | check(&mut () as *mut ());
|
||||
| ----- ^^^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*mut ()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `*const ()` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad.rs:12:11
|
||||
|
|
||||
LL | check(&() as *const ());
|
||||
| ----- ^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*const ()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad.rs:4:18
|
||||
|
|
||||
LL | fn check(_: impl std::marker::ConstParamTy) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,12 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NotParam;
|
||||
|
||||
fn check<T: std::marker::ConstParamTy>() {}
|
||||
|
||||
fn main() {
|
||||
check::<[NotParam; 0]>();
|
||||
//~^ error: `NotParam` can't be used as a const parameter type
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
error[E0277]: `NotParam` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_bad_empty_array.rs:10:13
|
||||
|
|
||||
LL | check::<[NotParam; 0]>();
|
||||
| ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`
|
||||
|
|
||||
= note: required for `[NotParam; 0]` to implement `ConstParamTy`
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_bad_empty_array.rs:7:13
|
||||
|
|
||||
LL | fn check<T: std::marker::ConstParamTy>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,13 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NotParam;
|
||||
|
||||
fn check<T: std::marker::ConstParamTy + ?Sized>() {}
|
||||
|
||||
fn main() {
|
||||
check::<&NotParam>(); //~ error: `NotParam` can't be used as a const parameter type
|
||||
check::<[NotParam]>(); //~ error: `NotParam` can't be used as a const parameter type
|
||||
check::<[NotParam; 17]>(); //~ error: `NotParam` can't be used as a const parameter type
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
error[E0277]: `NotParam` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13
|
||||
|
|
||||
LL | check::<&NotParam>();
|
||||
| ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`
|
||||
|
|
||||
= note: required for `&NotParam` to implement `ConstParamTy`
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
|
||||
|
|
||||
LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `NotParam` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13
|
||||
|
|
||||
LL | check::<[NotParam]>();
|
||||
| ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`
|
||||
|
|
||||
= note: required for `[NotParam]` to implement `ConstParamTy`
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
|
||||
|
|
||||
LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error[E0277]: `NotParam` can't be used as a const parameter type
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13
|
||||
|
|
||||
LL | check::<[NotParam; 17]>();
|
||||
| ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`
|
||||
|
|
||||
= note: required for `[NotParam; 17]` to implement `ConstParamTy`
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
|
||||
|
|
||||
LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,43 @@
|
||||
// check-pass
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct S<T> {
|
||||
field: u8,
|
||||
gen: T,
|
||||
}
|
||||
|
||||
impl<T: ConstParamTy> ConstParamTy for S<T> {}
|
||||
|
||||
fn check<T: ConstParamTy + ?Sized>() {}
|
||||
|
||||
fn main() {
|
||||
check::<u8>();
|
||||
check::<u16>();
|
||||
check::<u32>();
|
||||
check::<u64>();
|
||||
check::<u128>();
|
||||
|
||||
check::<i8>();
|
||||
check::<i16>();
|
||||
check::<i32>();
|
||||
check::<i64>();
|
||||
check::<i128>();
|
||||
|
||||
check::<char>();
|
||||
check::<bool>();
|
||||
check::<str>();
|
||||
|
||||
check::<&u8>();
|
||||
check::<&str>();
|
||||
check::<[usize]>();
|
||||
check::<[u16; 0]>();
|
||||
check::<[u8; 42]>();
|
||||
|
||||
check::<S<u8>>();
|
||||
check::<S<[&[bool]; 8]>>();
|
||||
|
||||
// FIXME: test tuples
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NotParam;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct CantParam(NotParam);
|
||||
|
||||
impl std::marker::ConstParamTy for CantParam {}
|
||||
//~^ error: the trait `ConstParamTy` cannot be implemented for this type
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,12 @@
|
||||
error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
|
||||
--> $DIR/const_param_ty_impl_bad_field.rs:10:36
|
||||
|
|
||||
LL | struct CantParam(NotParam);
|
||||
| -------- this field does not implement `ConstParamTy`
|
||||
LL |
|
||||
LL | impl std::marker::ConstParamTy for CantParam {}
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0204`.
|
@ -0,0 +1,17 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct ImplementsConstParamTy;
|
||||
impl std::marker::ConstParamTy for ImplementsConstParamTy {}
|
||||
|
||||
struct CantParam(ImplementsConstParamTy);
|
||||
|
||||
impl std::marker::ConstParamTy for CantParam {}
|
||||
//~^ error: the type `CantParam` does not `#[derive(Eq)]`
|
||||
|
||||
fn check<T: std::marker::ConstParamTy>() {}
|
||||
|
||||
fn main() {
|
||||
check::<ImplementsConstParamTy>();
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
error[E0277]: the type `CantParam` does not `#[derive(Eq)]`
|
||||
--> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
|
||||
|
|
||||
LL | impl std::marker::ConstParamTy for CantParam {}
|
||||
| ^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParam`
|
||||
|
|
||||
note: required by a bound in `ConstParamTy`
|
||||
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -10,6 +10,7 @@ pub trait Parse {
|
||||
|
||||
pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
|
||||
//~^ ERROR expected associated constant bound
|
||||
//~| ERROR expected associated constant bound
|
||||
//~| ERROR expected type
|
||||
|
||||
fn no_help() -> Mode::Cool {}
|
||||
|
@ -8,7 +8,7 @@ LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
|
||||
| help: try using the variant's enum: `Mode`
|
||||
|
||||
error[E0573]: expected type, found variant `Mode::Cool`
|
||||
--> $DIR/assoc_const_eq_diagnostic.rs:15:17
|
||||
--> $DIR/assoc_const_eq_diagnostic.rs:16:17
|
||||
|
|
||||
LL | fn no_help() -> Mode::Cool {}
|
||||
| ^^^^^^^^^^
|
||||
@ -28,6 +28,18 @@ note: associated constant defined here
|
||||
LL | const MODE: Mode;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: expected associated constant bound, found type
|
||||
--> $DIR/assoc_const_eq_diagnostic.rs:11:28
|
||||
|
|
||||
LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
|
||||
| ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }`
|
||||
|
|
||||
note: associated constant defined here
|
||||
--> $DIR/assoc_const_eq_diagnostic.rs:8:5
|
||||
|
|
||||
LL | const MODE: Mode;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0573`.
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![cfg_attr(full, feature(adt_const_params))]
|
||||
#![cfg_attr(full, allow(incomplete_features))]
|
||||
|
||||
struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
|
||||
struct Foo<const N: [u8; {
|
||||
struct Foo<const N: usize>;
|
||||
|
||||
impl<const N: usize> Foo<N> {
|
||||
@ -15,5 +15,9 @@ struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
|
||||
Foo::<17>::value()
|
||||
//~^ ERROR cannot call non-const fn
|
||||
}]>;
|
||||
//[min]~^^^^^^^^^^^^ ERROR `[u8; {
|
||||
|
||||
// N.B. it is important that the comment above is not inside the array length,
|
||||
// otherwise it may check for itself, instead of the actual error
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,6 @@
|
||||
trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
//~^ ERROR is already specified
|
||||
//~| ERROR is already specified
|
||||
|
||||
type Unit = ();
|
||||
|
||||
|
@ -7,13 +7,21 @@ LL | trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:6:42
|
||||
--> $DIR/E0719.rs:1:33
|
||||
|
|
||||
LL | trait Foo: Iterator<Item = i32, Item = i32> {}
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
|
||||
--> $DIR/E0719.rs:7:42
|
||||
|
|
||||
LL | fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> {
|
||||
| --------- ^^^^^^^^^^^ re-bound here
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0719`.
|
||||
|
@ -1,3 +0,0 @@
|
||||
#![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")] //~ ERROR the `#[debugger_visualizer]` attribute is an experimental feature
|
||||
|
||||
fn main() {}
|
@ -1,12 +0,0 @@
|
||||
error[E0658]: the `#[debugger_visualizer]` attribute is an experimental feature
|
||||
--> $DIR/feature-gate-debugger-visualizer.rs:1:1
|
||||
|
|
||||
LL | #![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #95939 <https://github.com/rust-lang/rust/issues/95939> for more information
|
||||
= help: add `#![feature(debugger_visualizer)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: return type notation is experimental
|
||||
--> $DIR/feature-gate-return_type_notation.rs:15:17
|
||||
--> $DIR/feature-gate-return_type_notation.rs:14:17
|
||||
|
|
||||
LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
| ^^^^^^^^^
|
||||
@ -7,17 +7,8 @@ LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= help: add `#![feature(return_type_notation)]` to the crate attributes to enable
|
||||
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/feature-gate-return_type_notation.rs:7:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: parenthesized generic arguments cannot be used in associated type constraints
|
||||
--> $DIR/feature-gate-return_type_notation.rs:15:17
|
||||
--> $DIR/feature-gate-return_type_notation.rs:14:17
|
||||
|
|
||||
LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
| ^--
|
||||
@ -25,12 +16,12 @@ LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
| help: remove these parentheses
|
||||
|
||||
error[E0220]: associated type `m` not found for `Trait`
|
||||
--> $DIR/feature-gate-return_type_notation.rs:15:17
|
||||
--> $DIR/feature-gate-return_type_notation.rs:14:17
|
||||
|
|
||||
LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
| ^ associated type `m` not found
|
||||
|
||||
error: aborting due to 3 previous errors; 1 warning emitted
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0220, E0658.
|
||||
For more information about an error, try `rustc --explain E0220`.
|
||||
|
@ -1,14 +1,5 @@
|
||||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/feature-gate-return_type_notation.rs:7:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: return type notation is experimental
|
||||
--> $DIR/feature-gate-return_type_notation.rs:15:17
|
||||
--> $DIR/feature-gate-return_type_notation.rs:14:17
|
||||
|
|
||||
LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
| ^^^^^^^^^
|
||||
@ -18,5 +9,5 @@ LL | fn foo<T: Trait<m(): Send>>() {}
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
// Since we're not adding new syntax, `cfg`'d out RTN must pass.
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete
|
||||
|
||||
trait Trait {
|
||||
async fn m();
|
||||
|
@ -17,7 +17,7 @@ fn main() {
|
||||
let _ = format!("}");
|
||||
//~^ ERROR invalid format string: unmatched `}` found
|
||||
let _ = format!("{\\}");
|
||||
//~^ ERROR invalid format string: expected `'}'`, found `'\\'`
|
||||
//~^ ERROR invalid format string: expected `'}'`, found `'\'`
|
||||
let _ = format!("\n\n\n{\n\n\n");
|
||||
//~^ ERROR invalid format string
|
||||
let _ = format!(r###"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user