Auto merge of #120242 - matthiaskrgr:rollup-a93yj3i, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #117910 (Refactor uses of `objc_msgSend` to no longer have clashing definitions) - #118639 (Undeprecate lint `unstable_features` and make use of it in the compiler) - #119801 (Fix deallocation with wrong allocator in (A)Rc::from_box_in) - #120058 (bootstrap: improvements for compiler builds) - #120059 (Make generic const type mismatches not hide trait impls from the trait solver) - #120097 (Report unreachable subpatterns consistently) - #120137 (Validate AggregateKind types in MIR) - #120164 (`maybe_lint_impl_trait`: separate `is_downgradable` from `is_object_safe`) - #120181 (Allow any `const` expression blocks in `thread_local!`) - #120218 (rustfmt: Check that a token can begin a nonterminal kind before parsing it as a macro arg) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d5fd099729
@ -796,7 +796,67 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
match rvalue {
|
match rvalue {
|
||||||
Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
|
Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
|
||||||
|
Rvalue::Aggregate(kind, fields) => match **kind {
|
||||||
|
AggregateKind::Tuple => {}
|
||||||
|
AggregateKind::Array(dest) => {
|
||||||
|
for src in fields {
|
||||||
|
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
|
||||||
|
self.fail(location, "array field has the wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AggregateKind::Adt(def_id, idx, args, _, Some(field)) => {
|
||||||
|
let adt_def = self.tcx.adt_def(def_id);
|
||||||
|
assert!(adt_def.is_union());
|
||||||
|
assert_eq!(idx, FIRST_VARIANT);
|
||||||
|
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
|
||||||
|
if fields.len() != 1 {
|
||||||
|
self.fail(location, "unions should have one initialized field");
|
||||||
|
}
|
||||||
|
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
|
||||||
|
self.fail(location, "union field has the wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AggregateKind::Adt(def_id, idx, args, _, None) => {
|
||||||
|
let adt_def = self.tcx.adt_def(def_id);
|
||||||
|
assert!(!adt_def.is_union());
|
||||||
|
let variant = &adt_def.variants()[idx];
|
||||||
|
if variant.fields.len() != fields.len() {
|
||||||
|
self.fail(location, "adt has the wrong number of initialized fields");
|
||||||
|
}
|
||||||
|
for (src, dest) in std::iter::zip(fields, &variant.fields) {
|
||||||
|
if !self.mir_assign_valid_types(
|
||||||
|
src.ty(self.body, self.tcx),
|
||||||
|
dest.ty(self.tcx, args),
|
||||||
|
) {
|
||||||
|
self.fail(location, "adt field has the wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AggregateKind::Closure(_, args) => {
|
||||||
|
let upvars = args.as_closure().upvar_tys();
|
||||||
|
if upvars.len() != fields.len() {
|
||||||
|
self.fail(location, "closure has the wrong number of initialized fields");
|
||||||
|
}
|
||||||
|
for (src, dest) in std::iter::zip(fields, upvars) {
|
||||||
|
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
|
||||||
|
self.fail(location, "closure field has the wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AggregateKind::Coroutine(_, args) => {
|
||||||
|
let upvars = args.as_coroutine().upvar_tys();
|
||||||
|
if upvars.len() != fields.len() {
|
||||||
|
self.fail(location, "coroutine has the wrong number of initialized fields");
|
||||||
|
}
|
||||||
|
for (src, dest) in std::iter::zip(fields, upvars) {
|
||||||
|
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
|
||||||
|
self.fail(location, "coroutine field has the wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Rvalue::Ref(_, BorrowKind::Fake, _) => {
|
Rvalue::Ref(_, BorrowKind::Fake, _) => {
|
||||||
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
|
||||||
self.fail(
|
self.fail(
|
||||||
|
@ -94,15 +94,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
|
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
|
||||||
|
let mut is_downgradable = true;
|
||||||
let is_object_safe = match self_ty.kind {
|
let is_object_safe = match self_ty.kind {
|
||||||
hir::TyKind::TraitObject(objects, ..) => {
|
hir::TyKind::TraitObject(objects, ..) => {
|
||||||
objects.iter().all(|o| match o.trait_ref.path.res {
|
objects.iter().all(|o| match o.trait_ref.path.res {
|
||||||
Res::Def(DefKind::Trait, id) if Some(id) == owner => {
|
Res::Def(DefKind::Trait, id) => {
|
||||||
// When we're dealing with a recursive trait, we don't want to downgrade
|
if Some(id) == owner {
|
||||||
// the error, so we consider them to be object safe always. (#119652)
|
// For recursive traits, don't downgrade the error. (#119652)
|
||||||
true
|
is_downgradable = false;
|
||||||
|
}
|
||||||
|
tcx.check_is_object_safe(id)
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -130,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
],
|
],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
} else if diag.is_error() {
|
} else if diag.is_error() && is_downgradable {
|
||||||
// We'll emit the object safety error already, with a structured suggestion.
|
// We'll emit the object safety error already, with a structured suggestion.
|
||||||
diag.downgrade_to_delayed_bug();
|
diag.downgrade_to_delayed_bug();
|
||||||
}
|
}
|
||||||
@ -156,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
if !is_object_safe {
|
if !is_object_safe {
|
||||||
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
|
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
|
||||||
if diag.is_error() {
|
if diag.is_error() && is_downgradable {
|
||||||
// We'll emit the object safety error already, with a structured suggestion.
|
// We'll emit the object safety error already, with a structured suggestion.
|
||||||
diag.downgrade_to_delayed_bug();
|
diag.downgrade_to_delayed_bug();
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
//
|
//
|
||||||
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
|
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
|
||||||
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
|
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
|
||||||
let compatible_types = self.probe(|_| {
|
self.probe(|_| {
|
||||||
if a.ty() == b.ty() {
|
if a.ty() == b.ty() {
|
||||||
return Ok(());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
|
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
|
||||||
@ -177,31 +177,17 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
relation.param_env().and((a.ty(), b.ty())),
|
relation.param_env().and((a.ty(), b.ty())),
|
||||||
&mut OriginalQueryValues::default(),
|
&mut OriginalQueryValues::default(),
|
||||||
);
|
);
|
||||||
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
|
self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
|
||||||
|
// The error will only be reported later. If we emit an ErrorGuaranteed
|
||||||
|
// here, then we will never get to the code that actually emits the error.
|
||||||
self.tcx.dcx().delayed_bug(format!(
|
self.tcx.dcx().delayed_bug(format!(
|
||||||
"cannot relate consts of different types (a={a:?}, b={b:?})",
|
"cannot relate consts of different types (a={a:?}, b={b:?})",
|
||||||
))
|
));
|
||||||
})
|
// We treat these constants as if they were of the same type, so that any
|
||||||
|
// such constants being used in impls make these impls match barring other mismatches.
|
||||||
|
// This helps with diagnostics down the road.
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the consts have differing types, just bail with a const error with
|
|
||||||
// the expected const's type. Specifically, we don't want const infer vars
|
|
||||||
// to do any type shapeshifting before and after resolution.
|
|
||||||
if let Err(guar) = compatible_types {
|
|
||||||
// HACK: equating both sides with `[const error]` eagerly prevents us
|
|
||||||
// from leaving unconstrained inference vars during things like impl
|
|
||||||
// matching in the solver.
|
|
||||||
let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
|
|
||||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
|
|
||||||
return self.unify_const_variable(vid, a_error, relation.param_env());
|
|
||||||
}
|
|
||||||
let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
|
|
||||||
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
|
|
||||||
return self.unify_const_variable(vid, b_error, relation.param_env());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(if relation.a_is_expected() { a_error } else { b_error });
|
|
||||||
}
|
|
||||||
|
|
||||||
match (a.kind(), b.kind()) {
|
match (a.kind(), b.kind()) {
|
||||||
(
|
(
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
|
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
// We want to be able to build this crate with a stable compiler, so no
|
// We want to be able to build this crate with a stable compiler,
|
||||||
// `#![feature]` attributes should be added.
|
// so no `#![feature]` attributes should be added.
|
||||||
|
#![deny(unstable_features)]
|
||||||
|
|
||||||
mod cursor;
|
mod cursor;
|
||||||
pub mod unescape;
|
pub mod unescape;
|
||||||
|
@ -148,7 +148,7 @@ lint_builtin_unsafe_impl = implementation of an `unsafe` trait
|
|||||||
|
|
||||||
lint_builtin_unsafe_trait = declaration of an `unsafe` trait
|
lint_builtin_unsafe_trait = declaration of an `unsafe` trait
|
||||||
|
|
||||||
lint_builtin_unstable_features = unstable feature
|
lint_builtin_unstable_features = use of an unstable feature
|
||||||
|
|
||||||
lint_builtin_unused_doc_comment = unused doc comment
|
lint_builtin_unused_doc_comment = unused doc comment
|
||||||
.label = rustdoc does not generate documentation for {$kind}
|
.label = rustdoc does not generate documentation for {$kind}
|
||||||
|
@ -1233,10 +1233,30 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `unstable_features` is deprecated and should no longer be used.
|
/// The `unstable_features` lint detects uses of `#![feature]`.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust,compile_fail
|
||||||
|
/// #![deny(unstable_features)]
|
||||||
|
/// #![feature(test)]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// In larger nightly-based projects which
|
||||||
|
///
|
||||||
|
/// * consist of a multitude of crates where a subset of crates has to compile on
|
||||||
|
/// stable either unconditionally or depending on a `cfg` flag to for example
|
||||||
|
/// allow stable users to depend on them,
|
||||||
|
/// * don't use nightly for experimental features but for, e.g., unstable options only,
|
||||||
|
///
|
||||||
|
/// this lint may come in handy to enforce policies of these kinds.
|
||||||
UNSTABLE_FEATURES,
|
UNSTABLE_FEATURES,
|
||||||
Allow,
|
Allow,
|
||||||
"enabling unstable features (deprecated. do not use)"
|
"enabling unstable features"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(
|
declare_lint_pass!(
|
||||||
@ -1246,14 +1266,14 @@ declare_lint_pass!(
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
||||||
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
|
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
|
||||||
if attr.has_name(sym::feature) {
|
if attr.has_name(sym::feature)
|
||||||
if let Some(items) = attr.meta_item_list() {
|
&& let Some(items) = attr.meta_item_list()
|
||||||
|
{
|
||||||
for item in items {
|
for item in items {
|
||||||
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
|
cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use rustc_pattern_analysis::errors::Uncovered;
|
use rustc_pattern_analysis::errors::Uncovered;
|
||||||
use rustc_pattern_analysis::rustc::{
|
use rustc_pattern_analysis::rustc::{
|
||||||
Constructor, DeconstructedPat, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
|
Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
|
||||||
UsefulnessReport, WitnessPat,
|
UsefulnessReport, WitnessPat,
|
||||||
};
|
};
|
||||||
use rustc_pattern_analysis::{analyze_match, MatchArm};
|
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
|
||||||
@ -390,6 +389,34 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn analyze_patterns(
|
||||||
|
&mut self,
|
||||||
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
|
arms: &[MatchArm<'p, 'tcx>],
|
||||||
|
scrut_ty: Ty<'tcx>,
|
||||||
|
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
|
||||||
|
let report =
|
||||||
|
rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
|
||||||
|
self.error = Err(err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Warn unreachable subpatterns.
|
||||||
|
for (arm, is_useful) in report.arm_usefulness.iter() {
|
||||||
|
if let Usefulness::Useful(redundant_subpats) = is_useful
|
||||||
|
&& !redundant_subpats.is_empty()
|
||||||
|
{
|
||||||
|
let mut redundant_subpats = redundant_subpats.clone();
|
||||||
|
// Emit lints in the order in which they occur in the file.
|
||||||
|
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
|
||||||
|
for pat in redundant_subpats {
|
||||||
|
report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(report)
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn check_let(&mut self, pat: &'p Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) {
|
fn check_let(&mut self, pat: &'p Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) {
|
||||||
assert!(self.let_source != LetSource::None);
|
assert!(self.let_source != LetSource::None);
|
||||||
@ -435,14 +462,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let scrut_ty = scrut.ty;
|
let Ok(report) = self.analyze_patterns(&cx, &tarms, scrut.ty) else { return };
|
||||||
let report = match analyze_match(&cx, &tarms, scrut_ty) {
|
|
||||||
Ok(report) => report,
|
|
||||||
Err(err) => {
|
|
||||||
self.error = Err(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match source {
|
match source {
|
||||||
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
|
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
|
||||||
@ -474,7 +494,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.error = Err(report_non_exhaustive_match(
|
self.error = Err(report_non_exhaustive_match(
|
||||||
&cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
|
&cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -556,7 +576,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
let cx = self.new_cx(refutability, None, scrut, pat.span);
|
let cx = self.new_cx(refutability, None, scrut, pat.span);
|
||||||
let pat = self.lower_pattern(&cx, pat)?;
|
let pat = self.lower_pattern(&cx, pat)?;
|
||||||
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
|
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
|
||||||
let report = analyze_match(&cx, &arms, pat.ty().inner())?;
|
let report = self.analyze_patterns(&cx, &arms, pat.ty().inner())?;
|
||||||
Ok((cx, report))
|
Ok((cx, report))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +587,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||||||
) -> Result<RefutableFlag, ErrorGuaranteed> {
|
) -> Result<RefutableFlag, ErrorGuaranteed> {
|
||||||
let (cx, report) = self.analyze_binding(pat, Refutable, scrut)?;
|
let (cx, report) = self.analyze_binding(pat, Refutable, scrut)?;
|
||||||
// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
|
// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
|
||||||
// This also reports unreachable sub-patterns.
|
|
||||||
report_arm_reachability(&cx, &report);
|
report_arm_reachability(&cx, &report);
|
||||||
// If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
|
// If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
|
||||||
// irrefutable.
|
// irrefutable.
|
||||||
@ -851,38 +870,29 @@ fn report_irrefutable_let_patterns(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Report unreachable arms, if any.
|
/// Report unreachable arms, if any.
|
||||||
fn report_arm_reachability<'p, 'tcx>(
|
fn report_unreachable_pattern<'p, 'tcx>(
|
||||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
report: &UsefulnessReport<'p, 'tcx>,
|
hir_id: HirId,
|
||||||
|
span: Span,
|
||||||
|
catchall: Option<Span>,
|
||||||
) {
|
) {
|
||||||
let report_unreachable_pattern = |span, hir_id, catchall: Option<Span>| {
|
|
||||||
cx.tcx.emit_spanned_lint(
|
cx.tcx.emit_spanned_lint(
|
||||||
UNREACHABLE_PATTERNS,
|
UNREACHABLE_PATTERNS,
|
||||||
hir_id,
|
hir_id,
|
||||||
span,
|
span,
|
||||||
UnreachablePattern {
|
UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
|
||||||
span: if catchall.is_some() { Some(span) } else { None },
|
|
||||||
catchall,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/// Report unreachable arms, if any.
|
||||||
|
fn report_arm_reachability<'p, 'tcx>(
|
||||||
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
|
report: &UsefulnessReport<'p, 'tcx>,
|
||||||
|
) {
|
||||||
let mut catchall = None;
|
let mut catchall = None;
|
||||||
for (arm, is_useful) in report.arm_usefulness.iter() {
|
for (arm, is_useful) in report.arm_usefulness.iter() {
|
||||||
match is_useful {
|
if matches!(is_useful, Usefulness::Redundant) {
|
||||||
Usefulness::Redundant => {
|
report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall)
|
||||||
report_unreachable_pattern(arm.pat.data().unwrap().span, arm.arm_data, catchall)
|
|
||||||
}
|
|
||||||
Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {}
|
|
||||||
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
|
|
||||||
Usefulness::Useful(redundant_subpats) => {
|
|
||||||
let mut redundant_subpats = redundant_subpats.clone();
|
|
||||||
// Emit lints in the order in which they occur in the file.
|
|
||||||
redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
|
|
||||||
for pat in redundant_subpats {
|
|
||||||
report_unreachable_pattern(pat.data().unwrap().span, arm.arm_data, None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
|
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
|
||||||
catchall = Some(arm.pat.data().unwrap().span);
|
catchall = Some(arm.pat.data().unwrap().span);
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
)]
|
)]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
// WARNING: We want to be able to build this crate with a stable compiler,
|
// We want to be able to build this crate with a stable compiler,
|
||||||
// so no `#![feature]` attributes should be added!
|
// so no `#![feature]` attributes should be added.
|
||||||
|
#![deny(unstable_features)]
|
||||||
|
|
||||||
use rustc_lexer::unescape;
|
use rustc_lexer::unescape;
|
||||||
pub use Alignment::*;
|
pub use Alignment::*;
|
||||||
|
@ -1924,7 +1924,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
|
|||||||
|
|
||||||
// Free the allocation without dropping its contents
|
// Free the allocation without dropping its contents
|
||||||
let (bptr, alloc) = Box::into_raw_with_allocator(src);
|
let (bptr, alloc) = Box::into_raw_with_allocator(src);
|
||||||
let src = Box::from_raw(bptr as *mut mem::ManuallyDrop<T>);
|
let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop<T>, alloc.by_ref());
|
||||||
drop(src);
|
drop(src);
|
||||||
|
|
||||||
Self::from_ptr_in(ptr, alloc)
|
Self::from_ptr_in(ptr, alloc)
|
||||||
|
@ -1869,7 +1869,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
|
|||||||
|
|
||||||
// Free the allocation without dropping its contents
|
// Free the allocation without dropping its contents
|
||||||
let (bptr, alloc) = Box::into_raw_with_allocator(src);
|
let (bptr, alloc) = Box::into_raw_with_allocator(src);
|
||||||
let src = Box::from_raw(bptr as *mut mem::ManuallyDrop<T>);
|
let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop<T>, alloc.by_ref());
|
||||||
drop(src);
|
drop(src);
|
||||||
|
|
||||||
Self::from_ptr_in(ptr, alloc)
|
Self::from_ptr_in(ptr, alloc)
|
||||||
|
@ -201,9 +201,9 @@ mod imp {
|
|||||||
|
|
||||||
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
||||||
// and use underscores in their names - they're most probably
|
// and use underscores in their names - they're most probably
|
||||||
// are considered private and therefore should be avoided
|
// are considered private and therefore should be avoided.
|
||||||
// Here is another way to get arguments using Objective C
|
// Here is another way to get arguments using the Objective-C
|
||||||
// runtime
|
// runtime.
|
||||||
//
|
//
|
||||||
// In general it looks like:
|
// In general it looks like:
|
||||||
// res = Vec::new()
|
// res = Vec::new()
|
||||||
@ -213,53 +213,60 @@ mod imp {
|
|||||||
// res
|
// res
|
||||||
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
|
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
|
||||||
pub fn args() -> Args {
|
pub fn args() -> Args {
|
||||||
use crate::ffi::OsString;
|
use crate::ffi::{c_char, c_void, OsString};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
|
|
||||||
|
type Sel = *const c_void;
|
||||||
|
type NsId = *const c_void;
|
||||||
|
type NSUInteger = usize;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
|
fn sel_registerName(name: *const c_char) -> Sel;
|
||||||
fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
|
fn objc_getClass(class_name: *const c_char) -> NsId;
|
||||||
|
|
||||||
|
// This must be transmuted to an appropriate function pointer type before being called.
|
||||||
|
fn objc_msgSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
const MSG_SEND_PTR: unsafe extern "C" fn() = objc_msgSend;
|
||||||
extern "C" {
|
const MSG_SEND_NO_ARGUMENTS_RETURN_PTR: unsafe extern "C" fn(NsId, Sel) -> *const c_void =
|
||||||
fn objc_msgSend(obj: NsId, sel: Sel) -> NsId;
|
unsafe { mem::transmute(MSG_SEND_PTR) };
|
||||||
#[allow(clashing_extern_declarations)]
|
const MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER: unsafe extern "C" fn(
|
||||||
#[link_name = "objc_msgSend"]
|
NsId,
|
||||||
fn objc_msgSend_ul(obj: NsId, sel: Sel, i: libc::c_ulong) -> NsId;
|
Sel,
|
||||||
}
|
) -> NSUInteger = unsafe { mem::transmute(MSG_SEND_PTR) };
|
||||||
|
const MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR: unsafe extern "C" fn(
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
NsId,
|
||||||
extern "C" {
|
Sel,
|
||||||
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
|
NSUInteger,
|
||||||
#[allow(clashing_extern_declarations)]
|
)
|
||||||
#[link_name = "objc_msgSend"]
|
-> *const c_void = unsafe { mem::transmute(MSG_SEND_PTR) };
|
||||||
fn objc_msgSend_ul(obj: NsId, sel: Sel, ...) -> NsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sel = *const libc::c_void;
|
|
||||||
type NsId = *const libc::c_void;
|
|
||||||
|
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let process_info_sel =
|
let process_info_sel = sel_registerName(c"processInfo".as_ptr());
|
||||||
sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar);
|
let arguments_sel = sel_registerName(c"arguments".as_ptr());
|
||||||
let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar);
|
let count_sel = sel_registerName(c"count".as_ptr());
|
||||||
let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar);
|
let object_at_index_sel = sel_registerName(c"objectAtIndex:".as_ptr());
|
||||||
let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar);
|
let utf8string_sel = sel_registerName(c"UTF8String".as_ptr());
|
||||||
let object_at_sel =
|
|
||||||
sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar);
|
|
||||||
|
|
||||||
let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar);
|
let klass = objc_getClass(c"NSProcessInfo".as_ptr());
|
||||||
let info = objc_msgSend(klass, process_info_sel);
|
// `+[NSProcessInfo processInfo]` returns an object with +0 retain count, so no need to manually `retain/release`.
|
||||||
let args = objc_msgSend(info, arguments_sel);
|
let info = MSG_SEND_NO_ARGUMENTS_RETURN_PTR(klass, process_info_sel);
|
||||||
|
|
||||||
let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
|
// `-[NSProcessInfo arguments]` returns an object with +0 retain count, so no need to manually `retain/release`.
|
||||||
|
let args = MSG_SEND_NO_ARGUMENTS_RETURN_PTR(info, arguments_sel);
|
||||||
|
|
||||||
|
let cnt = MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER(args, count_sel);
|
||||||
for i in 0..cnt {
|
for i in 0..cnt {
|
||||||
let tmp = objc_msgSend_ul(args, object_at_sel, i as libc::c_ulong);
|
// `-[NSArray objectAtIndex:]` returns an object whose lifetime is tied to the array, so no need to manually `retain/release`.
|
||||||
let utf_c_str: *const libc::c_char = mem::transmute(objc_msgSend(tmp, utf8_sel));
|
let ns_string =
|
||||||
|
MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR(args, object_at_index_sel, i);
|
||||||
|
// The lifetime of this pointer is tied to the NSString, as well as the current autorelease pool, which is why we heap-allocate the string below.
|
||||||
|
let utf_c_str: *const c_char =
|
||||||
|
MSG_SEND_NO_ARGUMENTS_RETURN_PTR(ns_string, utf8string_sel).cast();
|
||||||
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
|
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
|
||||||
res.push(OsString::from(str::from_utf8(bytes).unwrap()))
|
res.push(OsString::from(str::from_utf8(bytes).unwrap()))
|
||||||
}
|
}
|
||||||
|
@ -186,12 +186,12 @@ macro_rules! thread_local {
|
|||||||
// empty (base case for the recursion)
|
// empty (base case for the recursion)
|
||||||
() => {};
|
() => {};
|
||||||
|
|
||||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => (
|
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => (
|
||||||
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
|
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
|
||||||
$crate::thread_local!($($rest)*);
|
$crate::thread_local!($($rest)*);
|
||||||
);
|
);
|
||||||
|
|
||||||
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
|
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block) => (
|
||||||
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
|
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::cell::{Cell, RefCell};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -14,3 +15,24 @@ fn sleep() {
|
|||||||
thread::sleep(Duration::from_millis(100));
|
thread::sleep(Duration::from_millis(100));
|
||||||
assert_eq!(*finished.lock().unwrap(), false);
|
assert_eq!(*finished.lock().unwrap(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn thread_local_containing_const_statements() {
|
||||||
|
// This exercises the `const $init:block` cases of the thread_local macro.
|
||||||
|
// Despite overlapping with expression syntax, the `const { ... }` is not
|
||||||
|
// parsed as `$init:expr`.
|
||||||
|
thread_local! {
|
||||||
|
static CELL: Cell<u32> = const {
|
||||||
|
let value = 1;
|
||||||
|
Cell::new(value)
|
||||||
|
};
|
||||||
|
|
||||||
|
static REFCELL: RefCell<u32> = const {
|
||||||
|
let value = 1;
|
||||||
|
RefCell::new(value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(CELL.get(), 1);
|
||||||
|
assert_eq!(REFCELL.take(), 1);
|
||||||
|
}
|
||||||
|
@ -803,7 +803,14 @@ impl Rustc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Step for Rustc {
|
impl Step for Rustc {
|
||||||
type Output = ();
|
// We return the stage of the "actual" compiler (not the uplifted one).
|
||||||
|
//
|
||||||
|
// By "actual" we refer to the uplifting logic where we may not compile the requested stage;
|
||||||
|
// instead, we uplift it from the previous stages. Which can lead to bootstrap failures in
|
||||||
|
// specific situations where we request stage X from other steps. However we may end up
|
||||||
|
// uplifting it from stage Y, causing the other stage to fail when attempting to link with
|
||||||
|
// stage X which was never actually built.
|
||||||
|
type Output = u32;
|
||||||
const ONLY_HOSTS: bool = true;
|
const ONLY_HOSTS: bool = true;
|
||||||
const DEFAULT: bool = false;
|
const DEFAULT: bool = false;
|
||||||
|
|
||||||
@ -834,7 +841,7 @@ impl Step for Rustc {
|
|||||||
/// This will build the compiler for a particular stage of the build using
|
/// This will build the compiler for a particular stage of the build using
|
||||||
/// the `compiler` targeting the `target` architecture. The artifacts
|
/// the `compiler` targeting the `target` architecture. The artifacts
|
||||||
/// created will also be linked into the sysroot directory.
|
/// created will also be linked into the sysroot directory.
|
||||||
fn run(self, builder: &Builder<'_>) {
|
fn run(self, builder: &Builder<'_>) -> u32 {
|
||||||
let compiler = self.compiler;
|
let compiler = self.compiler;
|
||||||
let target = self.target;
|
let target = self.target;
|
||||||
|
|
||||||
@ -848,7 +855,7 @@ impl Step for Rustc {
|
|||||||
compiler,
|
compiler,
|
||||||
builder.config.ci_rustc_dev_contents(),
|
builder.config.ci_rustc_dev_contents(),
|
||||||
);
|
);
|
||||||
return;
|
return compiler.stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.ensure(Std::new(compiler, target));
|
builder.ensure(Std::new(compiler, target));
|
||||||
@ -857,7 +864,8 @@ impl Step for Rustc {
|
|||||||
builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
|
builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
|
||||||
builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
|
builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
|
||||||
builder.ensure(RustcLink::from_rustc(self, compiler));
|
builder.ensure(RustcLink::from_rustc(self, compiler));
|
||||||
return;
|
|
||||||
|
return compiler.stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
|
||||||
@ -880,7 +888,7 @@ impl Step for Rustc {
|
|||||||
};
|
};
|
||||||
builder.info(&msg);
|
builder.info(&msg);
|
||||||
builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
|
builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
|
||||||
return;
|
return compiler_to_use.stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that build scripts and proc macros have a std / libproc_macro to link against.
|
// Ensure that build scripts and proc macros have a std / libproc_macro to link against.
|
||||||
@ -984,6 +992,8 @@ impl Step for Rustc {
|
|||||||
self,
|
self,
|
||||||
builder.compiler(compiler.stage, builder.config.build),
|
builder.compiler(compiler.stage, builder.config.build),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
compiler.stage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1642,21 +1652,6 @@ impl Step for Assemble {
|
|||||||
return target_compiler;
|
return target_compiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the compiler that we'll use to bootstrap ourselves.
|
|
||||||
//
|
|
||||||
// Note that this is where the recursive nature of the bootstrap
|
|
||||||
// happens, as this will request the previous stage's compiler on
|
|
||||||
// downwards to stage 0.
|
|
||||||
//
|
|
||||||
// Also note that we're building a compiler for the host platform. We
|
|
||||||
// only assume that we can run `build` artifacts, which means that to
|
|
||||||
// produce some other architecture compiler we need to start from
|
|
||||||
// `build` to get there.
|
|
||||||
//
|
|
||||||
// FIXME: It may be faster if we build just a stage 1 compiler and then
|
|
||||||
// use that to bootstrap this compiler forward.
|
|
||||||
let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
|
|
||||||
|
|
||||||
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
|
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
|
||||||
if builder.download_rustc() {
|
if builder.download_rustc() {
|
||||||
let sysroot =
|
let sysroot =
|
||||||
@ -1671,19 +1666,30 @@ impl Step for Assemble {
|
|||||||
return target_compiler;
|
return target_compiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the compiler that we'll use to bootstrap ourselves.
|
||||||
|
//
|
||||||
|
// Note that this is where the recursive nature of the bootstrap
|
||||||
|
// happens, as this will request the previous stage's compiler on
|
||||||
|
// downwards to stage 0.
|
||||||
|
//
|
||||||
|
// Also note that we're building a compiler for the host platform. We
|
||||||
|
// only assume that we can run `build` artifacts, which means that to
|
||||||
|
// produce some other architecture compiler we need to start from
|
||||||
|
// `build` to get there.
|
||||||
|
//
|
||||||
|
// FIXME: It may be faster if we build just a stage 1 compiler and then
|
||||||
|
// use that to bootstrap this compiler forward.
|
||||||
|
let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
|
||||||
|
|
||||||
// Build the libraries for this compiler to link to (i.e., the libraries
|
// Build the libraries for this compiler to link to (i.e., the libraries
|
||||||
// it uses at runtime). NOTE: Crates the target compiler compiles don't
|
// it uses at runtime). NOTE: Crates the target compiler compiles don't
|
||||||
// link to these. (FIXME: Is that correct? It seems to be correct most
|
// link to these. (FIXME: Is that correct? It seems to be correct most
|
||||||
// of the time but I think we do link to these for stage2/bin compilers
|
// of the time but I think we do link to these for stage2/bin compilers
|
||||||
// when not performing a full bootstrap).
|
// when not performing a full bootstrap).
|
||||||
builder.ensure(Rustc::new(build_compiler, target_compiler.host));
|
let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
|
||||||
|
// Current build_compiler.stage might be uplifted instead of being built; so update it
|
||||||
// FIXME: For now patch over problems noted in #90244 by early returning here, even though
|
// to not fail while linking the artifacts.
|
||||||
// we've not properly assembled the target sysroot. A full fix is pending further investigation,
|
build_compiler.stage = actual_stage;
|
||||||
// for now full bootstrap usage is rare enough that this is OK.
|
|
||||||
if target_compiler.stage >= 3 && !builder.config.full_bootstrap {
|
|
||||||
return target_compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
for &backend in builder.config.rust_codegen_backends.iter() {
|
for &backend in builder.config.rust_codegen_backends.iter() {
|
||||||
if backend == "llvm" {
|
if backend == "llvm" {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use rustc_ast::token::{Delimiter, TokenKind};
|
use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind};
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::{ast, ptr};
|
use rustc_ast::{ast, ptr};
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
|
||||||
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::symbol::{self, kw};
|
use rustc_span::symbol::{self, kw};
|
||||||
@ -15,7 +15,7 @@ pub(crate) mod cfg_if;
|
|||||||
pub(crate) mod lazy_static;
|
pub(crate) mod lazy_static;
|
||||||
|
|
||||||
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
|
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
|
||||||
stream_to_parser(sess, tokens, MACRO_ARGUMENTS)
|
stream_to_parser(sess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
||||||
@ -24,16 +24,17 @@ fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser
|
|||||||
|
|
||||||
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
macro_rules! parse_macro_arg {
|
macro_rules! parse_macro_arg {
|
||||||
($macro_arg:ident, $parser:expr, $f:expr) => {
|
($macro_arg:ident, $nt_kind:expr, $try_parse:expr, $then:expr) => {
|
||||||
let mut cloned_parser = (*parser).clone();
|
let mut cloned_parser = (*parser).clone();
|
||||||
match $parser(&mut cloned_parser) {
|
if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) {
|
||||||
|
match $try_parse(&mut cloned_parser) {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
if parser.sess.dcx.has_errors().is_some() {
|
if parser.sess.dcx.has_errors().is_some() {
|
||||||
parser.sess.dcx.reset_err_count();
|
parser.sess.dcx.reset_err_count();
|
||||||
} else {
|
} else {
|
||||||
// Parsing succeeded.
|
// Parsing succeeded.
|
||||||
*parser = cloned_parser;
|
*parser = cloned_parser;
|
||||||
return Some(MacroArg::$macro_arg($f(x)?));
|
return Some(MacroArg::$macro_arg($then(x)?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -41,28 +42,33 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
|||||||
parser.sess.dcx.reset_err_count();
|
parser.sess.dcx.reset_err_count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Expr,
|
Expr,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
|
NonterminalKind::Expr,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_expr(),
|
||||||
|x: ptr::P<ast::Expr>| Some(x)
|
|x: ptr::P<ast::Expr>| Some(x)
|
||||||
);
|
);
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Ty,
|
Ty,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
|
NonterminalKind::Ty,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_ty(),
|
||||||
|x: ptr::P<ast::Ty>| Some(x)
|
|x: ptr::P<ast::Ty>| Some(x)
|
||||||
);
|
);
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Pat,
|
Pat,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
NonterminalKind::PatParam { inferred: false },
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
||||||
|x: ptr::P<ast::Pat>| Some(x)
|
|x: ptr::P<ast::Pat>| Some(x)
|
||||||
);
|
);
|
||||||
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Item,
|
Item,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
|
NonterminalKind::Item,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No),
|
||||||
|x: Option<ptr::P<ast::Item>>| x
|
|x: Option<ptr::P<ast::Item>>| x
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
m!(const N: usize = 0;);
|
@ -0,0 +1,3 @@
|
|||||||
|
m!(
|
||||||
|
const N: usize = 0;
|
||||||
|
);
|
@ -11,3 +11,4 @@ impl<const N: u64> Q for [u8; N] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
|
pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
|
||||||
|
//~^ ERROR: the constant `13` is not of type `u64`
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
|
error: the constant `13` is not of type `u64`
|
||||||
|
--> $DIR/bad-subst-const-kind.rs:13:24
|
||||||
|
|
|
||||||
|
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
|
||||||
|
| ^^^^^^^^ expected `u64`, found `usize`
|
||||||
|
|
|
||||||
|
note: required for `[u8; 13]` to implement `Q`
|
||||||
|
--> $DIR/bad-subst-const-kind.rs:8:20
|
||||||
|
|
|
||||||
|
LL | impl<const N: u64> Q for [u8; N] {
|
||||||
|
| ------------ ^ ^^^^^^^
|
||||||
|
| |
|
||||||
|
| unsatisfied trait bound introduced here
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/bad-subst-const-kind.rs:8:31
|
--> $DIR/bad-subst-const-kind.rs:8:31
|
||||||
|
|
|
|
||||||
LL | impl<const N: u64> Q for [u8; N] {
|
LL | impl<const N: u64> Q for [u8; N] {
|
||||||
| ^ expected `usize`, found `u64`
|
| ^ expected `usize`, found `u64`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
@ -7,7 +7,10 @@ trait Q {
|
|||||||
|
|
||||||
impl<const N: u64> Q for [u8; N] {}
|
impl<const N: u64> Q for [u8; N] {}
|
||||||
//~^ ERROR not all trait items implemented
|
//~^ ERROR not all trait items implemented
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
||||||
|
//~^ ERROR the constant `13` is not of type `u64`
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
@ -7,6 +7,35 @@ LL | const ASSOC: usize;
|
|||||||
LL | impl<const N: u64> Q for [u8; N] {}
|
LL | impl<const N: u64> Q for [u8; N] {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: the constant `13` is not of type `u64`
|
||||||
|
--> $DIR/type_mismatch.rs:12:26
|
||||||
|
|
|
||||||
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
||||||
|
| ^^^^^^^^ expected `u64`, found `usize`
|
||||||
|
|
|
||||||
|
note: required for `[u8; 13]` to implement `Q`
|
||||||
|
--> $DIR/type_mismatch.rs:8:20
|
||||||
|
|
|
||||||
|
LL | impl<const N: u64> Q for [u8; N] {}
|
||||||
|
| ------------ ^ ^^^^^^^
|
||||||
|
| |
|
||||||
|
| unsatisfied trait bound introduced here
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0046`.
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/type_mismatch.rs:12:20
|
||||||
|
|
|
||||||
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
||||||
|
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()`
|
||||||
|
| |
|
||||||
|
| implicitly returns `()` as its body has no tail or `return` expression
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/type_mismatch.rs:8:31
|
||||||
|
|
|
||||||
|
LL | impl<const N: u64> Q for [u8; N] {}
|
||||||
|
| ^ expected `usize`, found `u64`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0046, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0046`.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: unstable feature
|
error: use of an unstable feature
|
||||||
--> $DIR/feature-gate-feature-gate.rs:2:12
|
--> $DIR/feature-gate-feature-gate.rs:2:12
|
||||||
|
|
|
|
||||||
LL | #![feature(intrinsics)]
|
LL | #![feature(intrinsics)]
|
||||||
|
@ -160,3 +160,23 @@ fn main() {
|
|||||||
| (y, x) => {} //~ ERROR unreachable
|
| (y, x) => {} //~ ERROR unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unreachable_in_param((_ | (_, _)): (bool, bool)) {}
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
|
||||||
|
fn unreachable_in_binding() {
|
||||||
|
let bool_pair = (true, true);
|
||||||
|
let bool_option = Some(true);
|
||||||
|
|
||||||
|
let (_ | (_, _)) = bool_pair;
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
for (_ | (_, _)) in [bool_pair] {}
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
|
||||||
|
let (Some(_) | Some(true)) = bool_option else { return };
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
if let Some(_) | Some(true) = bool_option {}
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
while let Some(_) | Some(true) = bool_option {}
|
||||||
|
//~^ ERROR unreachable
|
||||||
|
}
|
||||||
|
@ -184,5 +184,41 @@ error: unreachable pattern
|
|||||||
LL | | (y, x) => {}
|
LL | | (y, x) => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to 29 previous errors
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:164:30
|
||||||
|
|
|
||||||
|
LL | fn unreachable_in_param((_ | (_, _)): (bool, bool)) {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:171:14
|
||||||
|
|
|
||||||
|
LL | let (_ | (_, _)) = bool_pair;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:173:14
|
||||||
|
|
|
||||||
|
LL | for (_ | (_, _)) in [bool_pair] {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:176:20
|
||||||
|
|
|
||||||
|
LL | let (Some(_) | Some(true)) = bool_option else { return };
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:178:22
|
||||||
|
|
|
||||||
|
LL | if let Some(_) | Some(true) = bool_option {}
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:180:25
|
||||||
|
|
|
||||||
|
LL | while let Some(_) | Some(true) = bool_option {}
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 35 previous errors
|
||||||
|
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:17:9
|
||||||
|
|
|
||||||
|
LL | Err(!),
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unreachable.rs:7:9
|
||||||
|
|
|
||||||
|
LL | #![deny(unreachable_patterns)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:20:19
|
||||||
|
|
|
||||||
|
LL | let (Ok(_x) | Err(!)) = res_void;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:22:12
|
||||||
|
|
|
||||||
|
LL | if let Err(!) = res_void {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:24:24
|
||||||
|
|
|
||||||
|
LL | if let (Ok(true) | Err(!)) = res_void {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:26:23
|
||||||
|
|
|
||||||
|
LL | for (Ok(mut _x) | Err(!)) in [res_void] {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/unreachable.rs:30:18
|
||||||
|
|
|
||||||
|
LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
31
tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
Normal file
31
tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// revisions: normal exh_pats
|
||||||
|
//[normal] check-pass
|
||||||
|
#![feature(never_patterns)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![cfg_attr(exh_pats, feature(exhaustive_patterns))]
|
||||||
|
#![allow(dead_code, unreachable_code)]
|
||||||
|
#![deny(unreachable_patterns)]
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum Void {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let res_void: Result<bool, Void> = Ok(true);
|
||||||
|
|
||||||
|
match res_void {
|
||||||
|
Ok(_x) => {}
|
||||||
|
Err(!),
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
||||||
|
}
|
||||||
|
let (Ok(_x) | Err(!)) = res_void;
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
||||||
|
if let Err(!) = res_void {}
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
||||||
|
if let (Ok(true) | Err(!)) = res_void {}
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
||||||
|
for (Ok(mut _x) | Err(!)) in [res_void] {}
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
|
||||||
|
//[exh_pats]~^ ERROR unreachable
|
@ -8,5 +8,6 @@ struct S<const L: usize>;
|
|||||||
impl<const N: i32> Copy for S<N> {}
|
impl<const N: i32> Copy for S<N> {}
|
||||||
//~^ ERROR the constant `N` is not of type `usize`
|
//~^ ERROR the constant `N` is not of type `usize`
|
||||||
impl<const M: usize> Copy for S<M> {}
|
impl<const M: usize> Copy for S<M> {}
|
||||||
|
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
|
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
|
||||||
|
--> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
|
||||||
|
|
|
||||||
|
LL | impl<const N: i32> Copy for S<N> {}
|
||||||
|
| -------------------------------- first implementation here
|
||||||
|
LL |
|
||||||
|
LL | impl<const M: usize> Copy for S<M> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
|
||||||
|
|
||||||
error: the constant `N` is not of type `usize`
|
error: the constant `N` is not of type `usize`
|
||||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
|
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
|
||||||
|
|
|
|
||||||
LL | impl<const N: i32> Copy for S<N> {}
|
LL | impl<const N: i32> Copy for S<N> {}
|
||||||
| ^^^^ expected `usize`, found `i32`
|
| ^^^^ expected `usize`, found `i32`
|
||||||
|
|
|
|
||||||
note: required by a bound in `S`
|
note: required for `S<N>` to implement `Clone`
|
||||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
|
--> $DIR/bad-const-wf-doesnt-specialize.rs:5:10
|
||||||
|
|
|
|
||||||
|
LL | #[derive(Clone)]
|
||||||
|
| ^^^^^
|
||||||
LL | struct S<const L: usize>;
|
LL | struct S<const L: usize>;
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `S`
|
| ----- unsatisfied trait bound introduced in this `derive` macro
|
||||||
|
note: required by a bound in `Copy`
|
||||||
|
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
||||||
|
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
||||||
|
@ -8,16 +8,18 @@ trait A: Sized {
|
|||||||
//~| ERROR the trait `A` cannot be made into an object
|
//~| ERROR the trait `A` cannot be made into an object
|
||||||
}
|
}
|
||||||
trait B {
|
trait B {
|
||||||
fn f(a: B) -> B;
|
fn f(b: B) -> B;
|
||||||
//~^ ERROR trait objects must include the `dyn` keyword
|
//~^ ERROR trait objects must include the `dyn` keyword
|
||||||
//~| ERROR trait objects must include the `dyn` keyword
|
//~| ERROR trait objects must include the `dyn` keyword
|
||||||
//~| ERROR associated item referring to unboxed trait object for its own trait
|
//~| ERROR associated item referring to unboxed trait object for its own trait
|
||||||
//~| ERROR the trait `B` cannot be made into an object
|
//~| ERROR the trait `B` cannot be made into an object
|
||||||
}
|
}
|
||||||
trait C {
|
trait C {
|
||||||
fn f(&self, a: C) -> C;
|
fn f(&self, c: C) -> C;
|
||||||
//~^ ERROR trait objects must include the `dyn` keyword
|
//~^ ERROR trait objects must include the `dyn` keyword
|
||||||
//~| ERROR trait objects must include the `dyn` keyword
|
//~| ERROR trait objects must include the `dyn` keyword
|
||||||
|
//~| ERROR associated item referring to unboxed trait object for its own trait
|
||||||
|
//~| ERROR the trait `C` cannot be made into an object
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -30,18 +30,18 @@ error: associated item referring to unboxed trait object for its own trait
|
|||||||
|
|
|
|
||||||
LL | trait B {
|
LL | trait B {
|
||||||
| - in this trait
|
| - in this trait
|
||||||
LL | fn f(a: B) -> B;
|
LL | fn f(b: B) -> B;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
|
|
|
|
||||||
help: you might have meant to use `Self` to refer to the implementing type
|
help: you might have meant to use `Self` to refer to the implementing type
|
||||||
|
|
|
|
||||||
LL | fn f(a: Self) -> Self;
|
LL | fn f(b: Self) -> Self;
|
||||||
| ~~~~ ~~~~
|
| ~~~~ ~~~~
|
||||||
|
|
||||||
error[E0038]: the trait `B` cannot be made into an object
|
error[E0038]: the trait `B` cannot be made into an object
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
|
||||||
|
|
|
|
||||||
LL | fn f(a: B) -> B;
|
LL | fn f(b: B) -> B;
|
||||||
| ^ `B` cannot be made into an object
|
| ^ `B` 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>
|
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>
|
||||||
@ -49,23 +49,53 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
|
|||||||
|
|
|
|
||||||
LL | trait B {
|
LL | trait B {
|
||||||
| - this trait cannot be made into an object...
|
| - this trait cannot be made into an object...
|
||||||
LL | fn f(a: B) -> B;
|
LL | fn f(b: B) -> B;
|
||||||
| ^ ...because associated function `f` has no `self` parameter
|
| ^ ...because associated function `f` has no `self` parameter
|
||||||
help: consider turning `f` into a method by giving it a `&self` argument
|
help: consider turning `f` into a method by giving it a `&self` argument
|
||||||
|
|
|
|
||||||
LL | fn f(&self, a: B) -> B;
|
LL | fn f(&self, b: B) -> B;
|
||||||
| ++++++
|
| ++++++
|
||||||
help: alternatively, consider constraining `f` so it does not apply to trait objects
|
help: alternatively, consider constraining `f` so it does not apply to trait objects
|
||||||
|
|
|
|
||||||
LL | fn f(a: B) -> B where Self: Sized;
|
LL | fn f(b: B) -> B where Self: Sized;
|
||||||
| +++++++++++++++++
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error: associated item referring to unboxed trait object for its own trait
|
||||||
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
|
||||||
|
|
|
||||||
|
LL | trait C {
|
||||||
|
| - in this trait
|
||||||
|
LL | fn f(&self, c: C) -> C;
|
||||||
|
| ^ ^
|
||||||
|
|
|
||||||
|
help: you might have meant to use `Self` to refer to the implementing type
|
||||||
|
|
|
||||||
|
LL | fn f(&self, c: Self) -> Self;
|
||||||
|
| ~~~~ ~~~~
|
||||||
|
|
||||||
|
error[E0038]: the trait `C` cannot be made into an object
|
||||||
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
|
||||||
|
|
|
||||||
|
LL | fn f(&self, c: C) -> C;
|
||||||
|
| ----- ^ `C` cannot be made into an object
|
||||||
|
| |
|
||||||
|
| help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self`
|
||||||
|
|
|
||||||
|
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-unsafe-trait-should-use-self-2021-without-dyn.rs:18:10
|
||||||
|
|
|
||||||
|
LL | trait C {
|
||||||
|
| - this trait cannot be made into an object...
|
||||||
|
LL | fn f(&self, c: C) -> C;
|
||||||
|
| ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
|
||||||
|
|
|
|
||||||
LL | fn f(a: A) -> A;
|
LL | fn f(a: A) -> A;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
|
= note: `A` it is not object safe, so it can't be `dyn`
|
||||||
help: use a new generic type parameter, constrained by `A`
|
help: use a new generic type parameter, constrained by `A`
|
||||||
|
|
|
|
||||||
LL | fn f<T: A>(a: T) -> A;
|
LL | fn f<T: A>(a: T) -> A;
|
||||||
@ -74,10 +104,6 @@ help: you can also use an opaque type, but users won't be able to specify the ty
|
|||||||
|
|
|
|
||||||
LL | fn f(a: impl A) -> A;
|
LL | fn f(a: impl A) -> A;
|
||||||
| ++++
|
| ++++
|
||||||
help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch
|
|
||||||
|
|
|
||||||
LL | fn f(a: &dyn A) -> A;
|
|
||||||
| ++++
|
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19
|
||||||
@ -85,84 +111,66 @@ error[E0782]: trait objects must include the `dyn` keyword
|
|||||||
LL | fn f(a: A) -> A;
|
LL | fn f(a: A) -> A;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use `impl A` to return an opaque type, as long as you return a single underlying type
|
help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type
|
||||||
|
|
|
|
||||||
LL | fn f(a: A) -> impl A;
|
LL | fn f(a: A) -> impl A;
|
||||||
| ++++
|
| ++++
|
||||||
help: alternatively, you can return an owned trait object
|
|
||||||
|
|
|
||||||
LL | fn f(a: A) -> Box<dyn A>;
|
|
||||||
| +++++++ +
|
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
|
||||||
|
|
|
|
||||||
LL | fn f(a: B) -> B;
|
LL | fn f(b: B) -> B;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
|
= note: `B` it is not object safe, so it can't be `dyn`
|
||||||
help: use a new generic type parameter, constrained by `B`
|
help: use a new generic type parameter, constrained by `B`
|
||||||
|
|
|
|
||||||
LL | fn f<T: B>(a: T) -> B;
|
LL | fn f<T: B>(b: T) -> B;
|
||||||
| ++++++ ~
|
| ++++++ ~
|
||||||
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
|
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
|
||||||
|
|
|
|
||||||
LL | fn f(a: impl B) -> B;
|
LL | fn f(b: impl B) -> B;
|
||||||
| ++++
|
|
||||||
help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch
|
|
||||||
|
|
|
||||||
LL | fn f(a: &dyn B) -> B;
|
|
||||||
| ++++
|
| ++++
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
|
||||||
|
|
|
|
||||||
LL | fn f(a: B) -> B;
|
LL | fn f(b: B) -> B;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use `impl B` to return an opaque type, as long as you return a single underlying type
|
help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type
|
||||||
|
|
|
|
||||||
LL | fn f(a: B) -> impl B;
|
LL | fn f(b: B) -> impl B;
|
||||||
| ++++
|
| ++++
|
||||||
help: alternatively, you can return an owned trait object
|
|
||||||
|
|
|
||||||
LL | fn f(a: B) -> Box<dyn B>;
|
|
||||||
| +++++++ +
|
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
|
||||||
|
|
|
|
||||||
LL | fn f(&self, a: C) -> C;
|
LL | fn f(&self, c: C) -> C;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
|
= note: `C` it is not object safe, so it can't be `dyn`
|
||||||
help: use a new generic type parameter, constrained by `C`
|
help: use a new generic type parameter, constrained by `C`
|
||||||
|
|
|
|
||||||
LL | fn f<T: C>(&self, a: T) -> C;
|
LL | fn f<T: C>(&self, c: T) -> C;
|
||||||
| ++++++ ~
|
| ++++++ ~
|
||||||
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
|
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
|
||||||
|
|
|
|
||||||
LL | fn f(&self, a: impl C) -> C;
|
LL | fn f(&self, c: impl C) -> C;
|
||||||
| ++++
|
|
||||||
help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch
|
|
||||||
|
|
|
||||||
LL | fn f(&self, a: &dyn C) -> C;
|
|
||||||
| ++++
|
| ++++
|
||||||
|
|
||||||
error[E0782]: trait objects must include the `dyn` keyword
|
error[E0782]: trait objects must include the `dyn` keyword
|
||||||
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
|
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
|
||||||
|
|
|
|
||||||
LL | fn f(&self, a: C) -> C;
|
LL | fn f(&self, c: C) -> C;
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
help: use `impl C` to return an opaque type, as long as you return a single underlying type
|
help: `C` is not object safe, use `impl C` to return an opaque type, as long as you return a single underlying type
|
||||||
|
|
|
|
||||||
LL | fn f(&self, a: C) -> impl C;
|
LL | fn f(&self, c: C) -> impl C;
|
||||||
| ++++
|
| ++++
|
||||||
help: alternatively, you can return an owned trait object
|
|
||||||
|
|
|
||||||
LL | fn f(&self, a: C) -> Box<dyn C>;
|
|
||||||
| +++++++ +
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 12 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0038, E0782.
|
Some errors have detailed explanations: E0038, E0782.
|
||||||
For more information about an error, try `rustc --explain E0038`.
|
For more information about an error, try `rustc --explain E0038`.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// run-pass
|
// run-pass
|
||||||
|
#![allow(unreachable_patterns)]
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user