Auto merge of #134318 - matthiaskrgr:rollup-jda0jkx, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #132939 (Suggest using deref in patterns) - #133293 (Updates Solaris target information, adds Solaris maintainer) - #133392 (Fix ICE when multiple supertrait substitutions need assoc but only one is provided) - #133986 (Add documentation for anonymous pipe module) - #134022 (Doc: Extend for tuples to be stabilized in 1.85.0) - #134259 (Clean up `infer_return_ty_for_fn_sig`) - #134264 (Arbitrary self types v2: Weak & NonNull diagnostics) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7caf35b2e5
37 changed files with 1153 additions and 330 deletions
|
@ -2025,6 +2025,22 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the specified expression needs parentheses for prefix
|
||||||
|
/// or postfix suggestions to be valid.
|
||||||
|
/// For example, `a + b` requires parentheses to suggest `&(a + b)`,
|
||||||
|
/// but just `a` does not.
|
||||||
|
/// Similarly, `(a + b).c()` also requires parentheses.
|
||||||
|
/// This should not be used for other types of suggestions.
|
||||||
|
pub fn expr_needs_parens(expr: &Expr<'_>) -> bool {
|
||||||
|
match expr.kind {
|
||||||
|
// parenthesize if needed (Issue #46756)
|
||||||
|
ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true,
|
||||||
|
// parenthesize borrows of range literals (Issue #54505)
|
||||||
|
_ if is_range_literal(expr) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum ExprKind<'hir> {
|
pub enum ExprKind<'hir> {
|
||||||
/// Allow anonymous constants from an inline `const` block
|
/// Allow anonymous constants from an inline `const` block
|
||||||
|
|
|
@ -249,6 +249,12 @@ hir_analysis_invalid_receiver_ty_help =
|
||||||
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
|
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
|
||||||
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||||
|
|
||||||
|
hir_analysis_invalid_receiver_ty_help_nonnull_note =
|
||||||
|
`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
|
hir_analysis_invalid_receiver_ty_help_weak_note =
|
||||||
|
`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
|
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
|
||||||
.note = type of `self` must be `Self` or a type that dereferences to it
|
.note = type of `self` must be `Self` or a type that dereferences to it
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir};
|
||||||
use crate::autoderef::Autoderef;
|
use crate::autoderef::Autoderef;
|
||||||
use crate::collect::CollectItemTypesVisitor;
|
use crate::collect::CollectItemTypesVisitor;
|
||||||
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
|
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
|
||||||
|
use crate::errors::InvalidReceiverTyHint;
|
||||||
use crate::{errors, fluent_generated as fluent};
|
use crate::{errors, fluent_generated as fluent};
|
||||||
|
|
||||||
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
|
||||||
|
@ -1749,7 +1750,18 @@ fn check_method_receiver<'tcx>(
|
||||||
{
|
{
|
||||||
match receiver_validity_err {
|
match receiver_validity_err {
|
||||||
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
|
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
|
||||||
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
let hint = match receiver_ty
|
||||||
|
.builtin_deref(false)
|
||||||
|
.unwrap_or(receiver_ty)
|
||||||
|
.ty_adt_def()
|
||||||
|
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
|
||||||
|
{
|
||||||
|
Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),
|
||||||
|
Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
|
||||||
}
|
}
|
||||||
ReceiverValidityError::DoesNotDeref => {
|
ReceiverValidityError::DoesNotDeref => {
|
||||||
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {
|
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {
|
||||||
|
|
|
@ -1340,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
|
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
|
||||||
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
|
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
|
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
|
||||||
|
@ -1357,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
|
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,18 +1407,37 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
|
||||||
ty::EarlyBinder::bind(output)
|
ty::EarlyBinder::bind(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_return_ty_for_fn_sig<'tcx>(
|
fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
|
||||||
sig: &hir::FnSig<'tcx>,
|
|
||||||
generics: &hir::Generics<'_>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
icx: &ItemCtxt<'tcx>,
|
icx: &ItemCtxt<'tcx>,
|
||||||
|
sig: &'tcx hir::FnSig<'tcx>,
|
||||||
|
generics: &'tcx hir::Generics<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
|
if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
|
||||||
|
return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
icx.lowerer().lower_fn_ty(
|
||||||
|
icx.tcx().local_def_id_to_hir_id(def_id),
|
||||||
|
sig.header.safety,
|
||||||
|
sig.header.abi,
|
||||||
|
sig.decl,
|
||||||
|
Some(generics),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recover_infer_ret_ty<'tcx>(
|
||||||
|
icx: &ItemCtxt<'tcx>,
|
||||||
|
infer_ret_ty: &'tcx hir::Ty<'tcx>,
|
||||||
|
generics: &'tcx hir::Generics<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
let tcx = icx.tcx;
|
let tcx = icx.tcx;
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||||
|
|
||||||
match sig.decl.output.get_infer_ret_ty() {
|
|
||||||
Some(ty) => {
|
|
||||||
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
|
||||||
|
|
||||||
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
// Typeck doesn't expect erased regions to be returned from `type_of`.
|
||||||
// This is a heuristic approach. If the scope has region parameters,
|
// This is a heuristic approach. If the scope has region parameters,
|
||||||
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
|
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
|
||||||
|
@ -1443,18 +1462,18 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut visitor = HirPlaceholderCollector::default();
|
let mut visitor = HirPlaceholderCollector::default();
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(infer_ret_ty);
|
||||||
|
|
||||||
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
|
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
|
||||||
let ret_ty = fn_sig.output();
|
let ret_ty = fn_sig.output();
|
||||||
|
|
||||||
// Don't leak types into signatures unless they're nameable!
|
// Don't leak types into signatures unless they're nameable!
|
||||||
// For example, if a function returns itself, we don't want that
|
// For example, if a function returns itself, we don't want that
|
||||||
// recursive function definition to leak out into the fn sig.
|
// recursive function definition to leak out into the fn sig.
|
||||||
let mut recovered_ret_ty = None;
|
let mut recovered_ret_ty = None;
|
||||||
|
|
||||||
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
|
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
ty.span,
|
infer_ret_ty.span,
|
||||||
"replace with the correct return type",
|
"replace with the correct return type",
|
||||||
suggestable_ret_ty,
|
suggestable_ret_ty,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
|
@ -1466,7 +1485,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||||
ret_ty,
|
ret_ty,
|
||||||
) {
|
) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
ty.span,
|
infer_ret_ty.span,
|
||||||
"replace with an appropriate return type",
|
"replace with an appropriate return type",
|
||||||
sugg,
|
sugg,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
|
@ -1474,6 +1493,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||||
} else if ret_ty.is_closure() {
|
} else if ret_ty.is_closure() {
|
||||||
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also note how `Fn` traits work just in case!
|
// Also note how `Fn` traits work just in case!
|
||||||
if ret_ty.is_closure() {
|
if ret_ty.is_closure() {
|
||||||
diag.note(
|
diag.note(
|
||||||
|
@ -1481,7 +1501,6 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||||
https://doc.rust-lang.org/book/ch13-01-closures.html",
|
https://doc.rust-lang.org/book/ch13-01-closures.html",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let guar = diag.emit();
|
let guar = diag.emit();
|
||||||
ty::Binder::dummy(tcx.mk_fn_sig(
|
ty::Binder::dummy(tcx.mk_fn_sig(
|
||||||
fn_sig.inputs().iter().copied(),
|
fn_sig.inputs().iter().copied(),
|
||||||
|
@ -1490,16 +1509,6 @@ fn infer_return_ty_for_fn_sig<'tcx>(
|
||||||
fn_sig.safety,
|
fn_sig.safety,
|
||||||
fn_sig.abi,
|
fn_sig.abi,
|
||||||
))
|
))
|
||||||
}
|
|
||||||
None => icx.lowerer().lower_fn_ty(
|
|
||||||
hir_id,
|
|
||||||
sig.header.safety,
|
|
||||||
sig.header.abi,
|
|
||||||
sig.decl,
|
|
||||||
Some(generics),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn suggest_impl_trait<'tcx>(
|
pub fn suggest_impl_trait<'tcx>(
|
||||||
|
|
|
@ -1655,6 +1655,14 @@ pub(crate) struct NonConstRange {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub(crate) enum InvalidReceiverTyHint {
|
||||||
|
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
|
||||||
|
Weak,
|
||||||
|
#[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)]
|
||||||
|
NonNull,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
|
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
|
||||||
#[note]
|
#[note]
|
||||||
|
@ -1673,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub receiver_ty: Ty<'tcx>,
|
pub receiver_ty: Ty<'tcx>,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub hint: Option<InvalidReceiverTyHint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::struct_span_code_err;
|
use rustc_errors::struct_span_code_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
|
||||||
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
|
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
|
@ -11,7 +10,7 @@ use rustc_middle::ty::{
|
||||||
self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
|
self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
|
||||||
TypeVisitableExt, Upcast,
|
TypeVisitableExt, Upcast,
|
||||||
};
|
};
|
||||||
use rustc_span::{ErrorGuaranteed, Span};
|
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||||
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
|
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
|
||||||
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
|
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
|
||||||
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
|
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
|
||||||
|
@ -128,8 +127,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default();
|
let mut needed_associated_types = FxIndexSet::default();
|
||||||
|
|
||||||
|
let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1);
|
||||||
let regular_traits_refs_spans = trait_bounds
|
let regular_traits_refs_spans = trait_bounds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
||||||
|
@ -145,13 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let bound_predicate = pred.kind();
|
let bound_predicate = pred.kind();
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||||
let pred = bound_predicate.rebind(pred);
|
// FIXME(negative_bounds): Handle this correctly...
|
||||||
associated_types.entry(original_span).or_default().extend(
|
let trait_ref =
|
||||||
tcx.associated_items(pred.def_id())
|
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
||||||
|
needed_associated_types.extend(
|
||||||
|
tcx.associated_items(trait_ref.def_id())
|
||||||
.in_definition_order()
|
.in_definition_order()
|
||||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||||
.filter(|item| !item.is_impl_trait_in_trait())
|
.filter(|item| !item.is_impl_trait_in_trait())
|
||||||
.map(|item| item.def_id),
|
// If the associated type has a `where Self: Sized` bound,
|
||||||
|
// we do not need to constrain the associated type.
|
||||||
|
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||||
|
.map(|item| (item.def_id, trait_ref)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
||||||
|
@ -201,10 +206,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
|
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
|
||||||
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
|
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
|
||||||
// corresponding `Projection` clause
|
// corresponding `Projection` clause
|
||||||
for def_ids in associated_types.values_mut() {
|
|
||||||
for (projection_bound, span) in &projection_bounds {
|
for (projection_bound, span) in &projection_bounds {
|
||||||
let def_id = projection_bound.item_def_id();
|
let def_id = projection_bound.item_def_id();
|
||||||
def_ids.swap_remove(&def_id);
|
let trait_ref = tcx.anonymize_bound_vars(
|
||||||
|
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
|
||||||
|
);
|
||||||
|
needed_associated_types.swap_remove(&(def_id, trait_ref));
|
||||||
if tcx.generics_require_sized_self(def_id) {
|
if tcx.generics_require_sized_self(def_id) {
|
||||||
tcx.emit_node_span_lint(
|
tcx.emit_node_span_lint(
|
||||||
UNUSED_ASSOCIATED_TYPE_BOUNDS,
|
UNUSED_ASSOCIATED_TYPE_BOUNDS,
|
||||||
|
@ -214,13 +221,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
|
|
||||||
// type in the `dyn Trait`.
|
|
||||||
def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(guar) = self.check_for_required_assoc_tys(
|
if let Err(guar) = self.check_for_required_assoc_tys(
|
||||||
associated_types,
|
principal_span,
|
||||||
|
needed_associated_types,
|
||||||
potential_assoc_types,
|
potential_assoc_types,
|
||||||
hir_trait_bounds,
|
hir_trait_bounds,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -721,53 +721,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
/// emit a generic note suggesting using a `where` clause to constraint instead.
|
/// emit a generic note suggesting using a `where` clause to constraint instead.
|
||||||
pub(crate) fn check_for_required_assoc_tys(
|
pub(crate) fn check_for_required_assoc_tys(
|
||||||
&self,
|
&self,
|
||||||
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
|
principal_span: Span,
|
||||||
|
missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
|
||||||
potential_assoc_types: Vec<usize>,
|
potential_assoc_types: Vec<usize>,
|
||||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
if associated_types.values().all(|v| v.is_empty()) {
|
if missing_assoc_types.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
// FIXME: Marked `mut` so that we can replace the spans further below with a more
|
// FIXME: This logic needs some more care w.r.t handling of conflicts
|
||||||
// appropriate one, but this should be handled earlier in the span assignment.
|
let missing_assoc_types: Vec<_> = missing_assoc_types
|
||||||
let associated_types: FxIndexMap<Span, Vec<_>> = associated_types
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(span, def_ids)| {
|
.map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
|
||||||
(span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default();
|
let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
|
||||||
let mut names_len = 0;
|
let mut names_len = 0;
|
||||||
|
|
||||||
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
|
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
|
||||||
// `issue-22560.rs`.
|
// `issue-22560.rs`.
|
||||||
let mut trait_bound_spans: Vec<Span> = vec![];
|
|
||||||
let mut dyn_compatibility_violations = Ok(());
|
let mut dyn_compatibility_violations = Ok(());
|
||||||
for (span, items) in &associated_types {
|
for (assoc_item, trait_ref) in &missing_assoc_types {
|
||||||
if !items.is_empty() {
|
names.entry(trait_ref).or_default().push(assoc_item.name);
|
||||||
trait_bound_spans.push(*span);
|
|
||||||
}
|
|
||||||
for assoc_item in items {
|
|
||||||
let trait_def_id = assoc_item.container_id(tcx);
|
|
||||||
names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name);
|
|
||||||
names_len += 1;
|
names_len += 1;
|
||||||
|
|
||||||
let violations =
|
let violations =
|
||||||
dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
|
dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
|
||||||
if !violations.is_empty() {
|
if !violations.is_empty() {
|
||||||
dyn_compatibility_violations = Err(report_dyn_incompatibility(
|
dyn_compatibility_violations = Err(report_dyn_incompatibility(
|
||||||
tcx,
|
tcx,
|
||||||
*span,
|
principal_span,
|
||||||
None,
|
None,
|
||||||
trait_def_id,
|
trait_ref.def_id(),
|
||||||
&violations,
|
&violations,
|
||||||
)
|
)
|
||||||
.emit());
|
.emit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(guar) = dyn_compatibility_violations {
|
if let Err(guar) = dyn_compatibility_violations {
|
||||||
return Err(guar);
|
return Err(guar);
|
||||||
|
@ -813,6 +804,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(trait_, mut assocs)| {
|
.map(|(trait_, mut assocs)| {
|
||||||
assocs.sort();
|
assocs.sort();
|
||||||
|
let trait_ = trait_.print_trait_sugared();
|
||||||
format!("{} in `{trait_}`", match &assocs[..] {
|
format!("{} in `{trait_}`", match &assocs[..] {
|
||||||
[] => String::new(),
|
[] => String::new(),
|
||||||
[only] => format!("`{only}`"),
|
[only] => format!("`{only}`"),
|
||||||
|
@ -826,10 +818,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
names.sort();
|
names.sort();
|
||||||
let names = names.join(", ");
|
let names = names.join(", ");
|
||||||
|
|
||||||
trait_bound_spans.sort();
|
|
||||||
let mut err = struct_span_code_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
trait_bound_spans,
|
principal_span,
|
||||||
E0191,
|
E0191,
|
||||||
"the value of the associated type{} {} must be specified",
|
"the value of the associated type{} {} must be specified",
|
||||||
pluralize!(names_len),
|
pluralize!(names_len),
|
||||||
|
@ -839,21 +830,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let mut types_count = 0;
|
let mut types_count = 0;
|
||||||
let mut where_constraints = vec![];
|
let mut where_constraints = vec![];
|
||||||
let mut already_has_generics_args_suggestion = false;
|
let mut already_has_generics_args_suggestion = false;
|
||||||
for (span, assoc_items) in &associated_types {
|
|
||||||
let mut names: UnordMap<_, usize> = Default::default();
|
let mut names: UnordMap<_, usize> = Default::default();
|
||||||
for item in assoc_items {
|
for (item, _) in &missing_assoc_types {
|
||||||
types_count += 1;
|
types_count += 1;
|
||||||
*names.entry(item.name).or_insert(0) += 1;
|
*names.entry(item.name).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
let mut dupes = false;
|
let mut dupes = false;
|
||||||
let mut shadows = false;
|
let mut shadows = false;
|
||||||
for item in assoc_items {
|
for (item, trait_ref) in &missing_assoc_types {
|
||||||
let prefix = if names[&item.name] > 1 {
|
let prefix = if names[&item.name] > 1 {
|
||||||
let trait_def_id = item.container_id(tcx);
|
let trait_def_id = trait_ref.def_id();
|
||||||
dupes = true;
|
dupes = true;
|
||||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||||
} else if bound_names.get(&item.name).is_some_and(|x| x != &item) {
|
} else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
|
||||||
let trait_def_id = item.container_id(tcx);
|
let trait_def_id = trait_ref.def_id();
|
||||||
shadows = true;
|
shadows = true;
|
||||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||||
} else {
|
} else {
|
||||||
|
@ -863,7 +854,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let mut is_shadowed = false;
|
let mut is_shadowed = false;
|
||||||
|
|
||||||
if let Some(assoc_item) = bound_names.get(&item.name)
|
if let Some(assoc_item) = bound_names.get(&item.name)
|
||||||
&& assoc_item != &item
|
&& *assoc_item != item
|
||||||
{
|
{
|
||||||
is_shadowed = true;
|
is_shadowed = true;
|
||||||
|
|
||||||
|
@ -884,16 +875,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if potential_assoc_types.len() == assoc_items.len() {
|
if potential_assoc_types.len() == missing_assoc_types.len() {
|
||||||
// When the amount of missing associated types equals the number of
|
// When the amount of missing associated types equals the number of
|
||||||
// extra type arguments present. A suggesting to replace the generic args with
|
// extra type arguments present. A suggesting to replace the generic args with
|
||||||
// associated types is already emitted.
|
// associated types is already emitted.
|
||||||
already_has_generics_args_suggestion = true;
|
already_has_generics_args_suggestion = true;
|
||||||
} else if let (Ok(snippet), false, false) =
|
} else if let (Ok(snippet), false, false) =
|
||||||
(tcx.sess.source_map().span_to_snippet(*span), dupes, shadows)
|
(tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
|
||||||
{
|
{
|
||||||
let types: Vec<_> =
|
let types: Vec<_> = missing_assoc_types
|
||||||
assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect();
|
.iter()
|
||||||
|
.map(|(item, _)| format!("{} = Type", item.name))
|
||||||
|
.collect();
|
||||||
let code = if snippet.ends_with('>') {
|
let code = if snippet.ends_with('>') {
|
||||||
// The user wrote `Trait<'a>` or similar and we don't have a type we can
|
// The user wrote `Trait<'a>` or similar and we don't have a type we can
|
||||||
// suggest, but at least we can clue them to the correct syntax
|
// suggest, but at least we can clue them to the correct syntax
|
||||||
|
@ -909,11 +902,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// least we can clue them to the correct syntax `Iterator<Item = Type>`.
|
// least we can clue them to the correct syntax `Iterator<Item = Type>`.
|
||||||
format!("{}<{}>", snippet, types.join(", "))
|
format!("{}<{}>", snippet, types.join(", "))
|
||||||
};
|
};
|
||||||
suggestions.push((*span, code));
|
suggestions.push((principal_span, code));
|
||||||
} else if dupes {
|
} else if dupes {
|
||||||
where_constraints.push(*span);
|
where_constraints.push(principal_span);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
|
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
|
||||||
using the fully-qualified path to the associated types";
|
using the fully-qualified path to the associated types";
|
||||||
if !where_constraints.is_empty() && suggestions.is_empty() {
|
if !where_constraints.is_empty() && suggestions.is_empty() {
|
||||||
|
@ -924,17 +917,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
if suggestions.len() != 1 || already_has_generics_args_suggestion {
|
if suggestions.len() != 1 || already_has_generics_args_suggestion {
|
||||||
// We don't need this label if there's an inline suggestion, show otherwise.
|
// We don't need this label if there's an inline suggestion, show otherwise.
|
||||||
for (span, assoc_items) in &associated_types {
|
|
||||||
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
|
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
|
||||||
for item in assoc_items {
|
for (item, _) in &missing_assoc_types {
|
||||||
types_count += 1;
|
types_count += 1;
|
||||||
*names.entry(item.name).or_insert(0) += 1;
|
*names.entry(item.name).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
let mut label = vec![];
|
let mut label = vec![];
|
||||||
for item in assoc_items {
|
for (item, trait_ref) in &missing_assoc_types {
|
||||||
let postfix = if names[&item.name] > 1 {
|
let postfix = if names[&item.name] > 1 {
|
||||||
let trait_def_id = item.container_id(tcx);
|
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
|
||||||
format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
|
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
@ -942,7 +933,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
if !label.is_empty() {
|
if !label.is_empty() {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
*span,
|
principal_span,
|
||||||
format!(
|
format!(
|
||||||
"associated type{} {} must be specified",
|
"associated type{} {} must be specified",
|
||||||
pluralize!(label.len()),
|
pluralize!(label.len()),
|
||||||
|
@ -951,7 +942,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
suggestions.sort_by_key(|&(span, _)| span);
|
suggestions.sort_by_key(|&(span, _)| span);
|
||||||
// There are cases where one bound points to a span within another bound's span, like when
|
// There are cases where one bound points to a span within another bound's span, like when
|
||||||
// you have code like the following (#115019), so we skip providing a suggestion in those
|
// you have code like the following (#115019), so we skip providing a suggestion in those
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
|
Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
|
||||||
Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind,
|
Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, expr_needs_parens,
|
||||||
};
|
};
|
||||||
use rustc_hir_analysis::collect::suggest_impl_trait;
|
use rustc_hir_analysis::collect::suggest_impl_trait;
|
||||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||||
|
@ -35,7 +35,6 @@ use tracing::{debug, instrument};
|
||||||
|
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
use crate::fn_ctxt::rustc_span::BytePos;
|
use crate::fn_ctxt::rustc_span::BytePos;
|
||||||
use crate::hir::is_range_literal;
|
|
||||||
use crate::method::probe;
|
use crate::method::probe;
|
||||||
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||||
use crate::{errors, fluent_generated as fluent};
|
use crate::{errors, fluent_generated as fluent};
|
||||||
|
@ -2648,7 +2647,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
|
let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
|
||||||
if self.needs_parentheses(expr) {
|
if expr_needs_parens(expr) {
|
||||||
(
|
(
|
||||||
vec![
|
vec![
|
||||||
(span.shrink_to_lo(), format!("{prefix}{sugg}(")),
|
(span.shrink_to_lo(), format!("{prefix}{sugg}(")),
|
||||||
|
@ -2861,7 +2860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.needs_parentheses(expr) {
|
if expr_needs_parens(expr) {
|
||||||
return Some((
|
return Some((
|
||||||
vec![
|
vec![
|
||||||
(span, format!("{suggestion}(")),
|
(span, format!("{suggestion}(")),
|
||||||
|
@ -2902,16 +2901,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool {
|
|
||||||
match expr.kind {
|
|
||||||
// parenthesize if needed (Issue #46756)
|
|
||||||
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
|
||||||
// parenthesize borrows of range literals (Issue #54505)
|
|
||||||
_ if is_range_literal(expr) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn suggest_cast(
|
pub(crate) fn suggest_cast(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
|
|
|
@ -10,8 +10,12 @@ use rustc_errors::{
|
||||||
};
|
};
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
|
use rustc_hir::{
|
||||||
|
self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatKind,
|
||||||
|
expr_needs_parens,
|
||||||
|
};
|
||||||
use rustc_infer::infer;
|
use rustc_infer::infer;
|
||||||
|
use rustc_middle::traits::PatternOriginExpr;
|
||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||||
|
@ -94,10 +98,32 @@ struct PatInfo<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
|
fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
|
||||||
|
// If origin_expr exists, then expected represents the type of origin_expr.
|
||||||
|
// If span also exists, then span == origin_expr.span (although it doesn't need to exist).
|
||||||
|
// In that case, we can peel away references from both and treat them
|
||||||
|
// as the same.
|
||||||
|
let origin_expr_info = ti.origin_expr.map(|mut cur_expr| {
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
// cur_ty may have more layers of references than cur_expr.
|
||||||
|
// We can only make suggestions about cur_expr, however, so we'll
|
||||||
|
// use that as our condition for stopping.
|
||||||
|
while let ExprKind::AddrOf(.., inner) = &cur_expr.kind {
|
||||||
|
cur_expr = inner;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PatternOriginExpr {
|
||||||
|
peeled_span: cur_expr.span,
|
||||||
|
peeled_count: count,
|
||||||
|
peeled_prefix_suggestion_parentheses: expr_needs_parens(cur_expr),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let code = ObligationCauseCode::Pattern {
|
let code = ObligationCauseCode::Pattern {
|
||||||
span: ti.span,
|
span: ti.span,
|
||||||
root_ty: ti.expected,
|
root_ty: ti.expected,
|
||||||
origin_expr: ti.origin_expr.is_some(),
|
origin_expr: origin_expr_info,
|
||||||
};
|
};
|
||||||
self.cause(cause_span, code)
|
self.cause(cause_span, code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,8 +316,8 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
/// The root expected type induced by a scrutinee or type expression.
|
/// The root expected type induced by a scrutinee or type expression.
|
||||||
root_ty: Ty<'tcx>,
|
root_ty: Ty<'tcx>,
|
||||||
/// Whether the `Span` came from an expression or a type expression.
|
/// Information about the `Span`, if it came from an expression, otherwise `None`.
|
||||||
origin_expr: bool,
|
origin_expr: Option<PatternOriginExpr>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Computing common supertype in an if expression
|
/// Computing common supertype in an if expression
|
||||||
|
@ -530,6 +530,25 @@ pub struct MatchExpressionArmCause<'tcx> {
|
||||||
pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
|
pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about the origin expression of a pattern, relevant to diagnostics.
|
||||||
|
/// Fields here refer to the scrutinee of a pattern.
|
||||||
|
/// If the scrutinee isn't given in the diagnostic, then this won't exist.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
||||||
|
pub struct PatternOriginExpr {
|
||||||
|
/// A span representing the scrutinee expression, with all leading references
|
||||||
|
/// peeled from the expression.
|
||||||
|
/// Only references in the expression are peeled - if the expression refers to a variable
|
||||||
|
/// whose type is a reference, then that reference is kept because it wasn't created
|
||||||
|
/// in the expression.
|
||||||
|
pub peeled_span: Span,
|
||||||
|
/// The number of references that were peeled to produce `peeled_span`.
|
||||||
|
pub peeled_count: usize,
|
||||||
|
/// Does the peeled expression need to be wrapped in parentheses for
|
||||||
|
/// a prefix suggestion (i.e., dereference) to be valid.
|
||||||
|
pub peeled_prefix_suggestion_parentheses: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
||||||
pub struct IfExpressionCause<'tcx> {
|
pub struct IfExpressionCause<'tcx> {
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "sparcv9-sun-solaris".into(),
|
llvm_target: "sparcv9-sun-solaris".into(),
|
||||||
metadata: crate::spec::TargetMetadata {
|
metadata: crate::spec::TargetMetadata {
|
||||||
description: Some("SPARC Solaris 11, illumos".into()),
|
description: Some("SPARC Solaris 11.4".into()),
|
||||||
tier: Some(2),
|
tier: Some(2),
|
||||||
host_tools: Some(false),
|
host_tools: Some(false),
|
||||||
std: Some(true),
|
std: Some(true),
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
|
||||||
Target {
|
Target {
|
||||||
llvm_target: "x86_64-pc-solaris".into(),
|
llvm_target: "x86_64-pc-solaris".into(),
|
||||||
metadata: crate::spec::TargetMetadata {
|
metadata: crate::spec::TargetMetadata {
|
||||||
description: Some("64-bit Solaris 11, illumos".into()),
|
description: Some("64-bit Solaris 11.4".into()),
|
||||||
tier: Some(2),
|
tier: Some(2),
|
||||||
host_tools: Some(false),
|
host_tools: Some(false),
|
||||||
std: Some(true),
|
std: Some(true),
|
||||||
|
|
|
@ -63,10 +63,11 @@ use rustc_hir::{self as hir};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::dep_graph::DepContext;
|
use rustc_middle::dep_graph::DepContext;
|
||||||
|
use rustc_middle::traits::PatternOriginExpr;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
|
||||||
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, with_forced_trimmed_paths};
|
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, with_forced_trimmed_paths};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
||||||
TypeVisitableExt,
|
TypeVisitableExt,
|
||||||
};
|
};
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
|
@ -77,7 +78,7 @@ use crate::error_reporting::TypeErrCtxt;
|
||||||
use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
|
use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
|
||||||
use crate::infer;
|
use crate::infer;
|
||||||
use crate::infer::relate::{self, RelateResult, TypeRelation};
|
use crate::infer::relate::{self, RelateResult, TypeRelation};
|
||||||
use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
|
use crate::infer::{InferCtxt, InferCtxtExt as _, TypeTrace, ValuePairs};
|
||||||
use crate::solve::deeply_normalize_for_diagnostics;
|
use crate::solve::deeply_normalize_for_diagnostics;
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||||
|
@ -433,15 +434,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||||
terr: TypeError<'tcx>,
|
terr: TypeError<'tcx>,
|
||||||
|
param_env: Option<ParamEnv<'tcx>>,
|
||||||
) {
|
) {
|
||||||
match *cause.code() {
|
match *cause.code() {
|
||||||
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
|
ObligationCauseCode::Pattern {
|
||||||
let ty = self.resolve_vars_if_possible(root_ty);
|
origin_expr: Some(origin_expr),
|
||||||
if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
|
span: Some(span),
|
||||||
{
|
root_ty,
|
||||||
|
} => {
|
||||||
|
let expected_ty = self.resolve_vars_if_possible(root_ty);
|
||||||
|
if !matches!(
|
||||||
|
expected_ty.kind(),
|
||||||
|
ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))
|
||||||
|
) {
|
||||||
// don't show type `_`
|
// don't show type `_`
|
||||||
if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
|
if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
|
||||||
&& let ty::Adt(def, args) = ty.kind()
|
&& let ty::Adt(def, args) = expected_ty.kind()
|
||||||
&& Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
|
&& Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
|
||||||
{
|
{
|
||||||
err.span_label(
|
err.span_label(
|
||||||
|
@ -449,22 +457,48 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
format!("this is an iterator with items of type `{}`", args.type_at(0)),
|
format!("this is an iterator with items of type `{}`", args.type_at(0)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
err.span_label(span, format!("this expression has type `{ty}`"));
|
err.span_label(span, format!("this expression has type `{expected_ty}`"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
|
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
|
||||||
&& ty.boxed_ty() == Some(found)
|
&& let Ok(mut peeled_snippet) =
|
||||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
self.tcx.sess.source_map().span_to_snippet(origin_expr.peeled_span)
|
||||||
{
|
{
|
||||||
err.span_suggestion(
|
// Parentheses are needed for cases like as casts.
|
||||||
|
// We use the peeled_span for deref suggestions.
|
||||||
|
// It's also safe to use for box, since box only triggers if there
|
||||||
|
// wasn't a reference to begin with.
|
||||||
|
if origin_expr.peeled_prefix_suggestion_parentheses {
|
||||||
|
peeled_snippet = format!("({peeled_snippet})");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try giving a box suggestion first, as it is a special case of the
|
||||||
|
// deref suggestion.
|
||||||
|
if expected_ty.boxed_ty() == Some(found) {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"consider dereferencing the boxed value",
|
"consider dereferencing the boxed value",
|
||||||
format!("*{snippet}"),
|
format!("*{peeled_snippet}"),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
|
} else if let Some(param_env) = param_env
|
||||||
|
&& let Some(prefix) = self.should_deref_suggestion_on_mismatch(
|
||||||
|
param_env,
|
||||||
|
found,
|
||||||
|
expected_ty,
|
||||||
|
origin_expr,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
"consider dereferencing to access the inner value using the Deref trait",
|
||||||
|
format!("{prefix}{peeled_snippet}"),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
|
}
|
||||||
|
ObligationCauseCode::Pattern { origin_expr: None, span: Some(span), .. } => {
|
||||||
err.span_label(span, "expected due to this");
|
err.span_label(span, "expected due to this");
|
||||||
}
|
}
|
||||||
ObligationCauseCode::BlockTailExpression(
|
ObligationCauseCode::BlockTailExpression(
|
||||||
|
@ -618,6 +652,45 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determines whether deref_to == <deref_from as Deref>::Target, and if so,
|
||||||
|
/// returns a prefix that should be added to deref_from as a suggestion.
|
||||||
|
fn should_deref_suggestion_on_mismatch(
|
||||||
|
&self,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
deref_to: Ty<'tcx>,
|
||||||
|
deref_from: Ty<'tcx>,
|
||||||
|
origin_expr: PatternOriginExpr,
|
||||||
|
) -> Option<String> {
|
||||||
|
// origin_expr contains stripped away versions of our expression.
|
||||||
|
// We'll want to use that to avoid suggesting things like *&x.
|
||||||
|
// However, the type that we have access to hasn't been stripped away,
|
||||||
|
// so we need to ignore the first n dereferences, where n is the number
|
||||||
|
// that's been stripped away in origin_expr.
|
||||||
|
|
||||||
|
// Find a way to autoderef from deref_from to deref_to.
|
||||||
|
let Some((num_derefs, (after_deref_ty, _))) = (self.autoderef_steps)(deref_from)
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, (ty, _))| self.infcx.can_eq(param_env, *ty, deref_to))
|
||||||
|
else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
if num_derefs <= origin_expr.peeled_count {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let deref_part = "*".repeat(num_derefs - origin_expr.peeled_count);
|
||||||
|
|
||||||
|
// If the user used a reference in the original expression, they probably
|
||||||
|
// want the suggestion to still give a reference.
|
||||||
|
if deref_from.is_ref() && !after_deref_ty.is_ref() {
|
||||||
|
Some(format!("&{deref_part}"))
|
||||||
|
} else {
|
||||||
|
Some(deref_part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
|
/// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
|
||||||
/// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
|
/// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
|
||||||
/// populate `other_value` with `other_ty`.
|
/// populate `other_value` with `other_ty`.
|
||||||
|
@ -1406,8 +1479,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
Variable(ty::error::ExpectedFound<Ty<'a>>),
|
Variable(ty::error::ExpectedFound<Ty<'a>>),
|
||||||
Fixed(&'static str),
|
Fixed(&'static str),
|
||||||
}
|
}
|
||||||
let (expected_found, exp_found, is_simple_error, values) = match values {
|
let (expected_found, exp_found, is_simple_error, values, param_env) = match values {
|
||||||
None => (None, Mismatch::Fixed("type"), false, None),
|
None => (None, Mismatch::Fixed("type"), false, None, None),
|
||||||
Some(ty::ParamEnvAnd { param_env, value: values }) => {
|
Some(ty::ParamEnvAnd { param_env, value: values }) => {
|
||||||
let mut values = self.resolve_vars_if_possible(values);
|
let mut values = self.resolve_vars_if_possible(values);
|
||||||
if self.next_trait_solver() {
|
if self.next_trait_solver() {
|
||||||
|
@ -1459,7 +1532,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
diag.downgrade_to_delayed_bug();
|
diag.downgrade_to_delayed_bug();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
(Some(vals), exp_found, is_simple_error, Some(values))
|
(Some(vals), exp_found, is_simple_error, Some(values), Some(param_env))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1791,7 +1864,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// It reads better to have the error origin as the final
|
// It reads better to have the error origin as the final
|
||||||
// thing.
|
// thing.
|
||||||
self.note_error_origin(diag, cause, exp_found, terr);
|
self.note_error_origin(diag, cause, exp_found, terr, param_env);
|
||||||
|
|
||||||
debug!(?diag);
|
debug!(?diag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
|
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
|
||||||
{
|
{
|
||||||
ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => {
|
ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => {
|
||||||
origin_expr.then_some(ConsiderAddingAwait::FutureSugg {
|
origin_expr.is_some().then_some(ConsiderAddingAwait::FutureSugg {
|
||||||
span: then_span.shrink_to_hi(),
|
span: then_span.shrink_to_hi(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, is_range_literal,
|
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, expr_needs_parens,
|
||||||
|
is_range_literal,
|
||||||
};
|
};
|
||||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
|
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
|
||||||
use rustc_middle::hir::map;
|
use rustc_middle::hir::map;
|
||||||
|
@ -1391,13 +1392,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
let Some(expr) = expr_finder.result else {
|
let Some(expr) = expr_finder.result else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let needs_parens = match expr.kind {
|
let needs_parens = expr_needs_parens(expr);
|
||||||
// parenthesize if needed (Issue #46756)
|
|
||||||
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
|
|
||||||
// parenthesize borrows of range literals (Issue #54505)
|
|
||||||
_ if is_range_literal(expr) => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = if needs_parens { span } else { span.shrink_to_lo() };
|
let span = if needs_parens { span } else { span.shrink_to_lo() };
|
||||||
let suggestions = if !needs_parens {
|
let suggestions = if !needs_parens {
|
||||||
|
|
|
@ -493,15 +493,64 @@ impl Extend<()> for () {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! spec_tuple_impl {
|
macro_rules! spec_tuple_impl {
|
||||||
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
|
(
|
||||||
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
|
(
|
||||||
|
$ty_name:ident, $var_name:ident, $extend_ty_name: ident,
|
||||||
|
$trait_name:ident, $default_fn_name:ident, $cnt:tt
|
||||||
|
),
|
||||||
|
) => {
|
||||||
|
spec_tuple_impl!(
|
||||||
|
$trait_name,
|
||||||
|
$default_fn_name,
|
||||||
|
#[doc(fake_variadic)]
|
||||||
|
#[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for \
|
||||||
|
1- and 3- through 12-ary tuples were stabilized after 2-tuples, in \
|
||||||
|
CURRENT_RUSTC_VERSION."]
|
||||||
|
=> ($ty_name, $var_name, $extend_ty_name, $cnt),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {
|
(
|
||||||
|
(
|
||||||
spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
|
$ty_name:ident, $var_name:ident, $extend_ty_name: ident,
|
||||||
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
|
$trait_name:ident, $default_fn_name:ident, $cnt:tt
|
||||||
|
),
|
||||||
|
$(
|
||||||
|
(
|
||||||
|
$ty_names:ident, $var_names:ident, $extend_ty_names:ident,
|
||||||
|
$trait_names:ident, $default_fn_names:ident, $cnts:tt
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
spec_tuple_impl!(
|
||||||
|
$(
|
||||||
|
(
|
||||||
|
$ty_names, $var_names, $extend_ty_names,
|
||||||
|
$trait_names, $default_fn_names, $cnts
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
);
|
||||||
|
spec_tuple_impl!(
|
||||||
|
$trait_name,
|
||||||
|
$default_fn_name,
|
||||||
|
#[doc(hidden)]
|
||||||
|
=> (
|
||||||
|
$ty_name, $var_name, $extend_ty_name, $cnt
|
||||||
|
),
|
||||||
|
$(
|
||||||
|
(
|
||||||
|
$ty_names, $var_names, $extend_ty_names, $cnts
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
);
|
||||||
};
|
};
|
||||||
($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
|
(
|
||||||
|
$trait_name:ident, $default_fn_name:ident, #[$meta:meta]
|
||||||
|
$(#[$doctext:meta])? => $(
|
||||||
|
(
|
||||||
|
$ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt
|
||||||
|
),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
#[$meta]
|
#[$meta]
|
||||||
$(#[$doctext])?
|
$(#[$doctext])?
|
||||||
#[stable(feature = "extend_for_tuple", since = "1.56.0")]
|
#[stable(feature = "extend_for_tuple", since = "1.56.0")]
|
||||||
|
|
|
@ -1,20 +1,66 @@
|
||||||
//! Module for anonymous pipe
|
//! A cross-platform anonymous pipe.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on
|
||||||
|
//! Windows.
|
||||||
|
//!
|
||||||
|
//! # Behavior
|
||||||
|
//!
|
||||||
|
//! A pipe is a synchronous, unidirectional data channel between two or more processes, like an
|
||||||
|
//! interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
|
||||||
|
//!
|
||||||
|
//! * A read on a [`PipeReader`] blocks until the pipe is non-empty.
|
||||||
|
//! * A write on a [`PipeWriter`] blocks when the pipe is full.
|
||||||
|
//! * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
|
||||||
|
//! returns EOF.
|
||||||
|
//! * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
|
||||||
|
//!
|
||||||
|
//! # Capacity
|
||||||
|
//!
|
||||||
|
//! Pipe capacity is platform dependent. To quote the Linux [man page]:
|
||||||
|
//!
|
||||||
|
//! > Different implementations have different limits for the pipe capacity. Applications should
|
||||||
|
//! > not rely on a particular capacity: an application should be designed so that a reading process
|
||||||
|
//! > consumes data as soon as it is available, so that a writing process does not remain blocked.
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
//! #![feature(anonymous_pipe)]
|
//! #![feature(anonymous_pipe)]
|
||||||
//!
|
|
||||||
//! # #[cfg(miri)] fn main() {}
|
//! # #[cfg(miri)] fn main() {}
|
||||||
//! # #[cfg(not(miri))]
|
//! # #[cfg(not(miri))]
|
||||||
//! # fn main() -> std::io::Result<()> {
|
//! # fn main() -> std::io::Result<()> {
|
||||||
//! let (reader, writer) = std::pipe::pipe()?;
|
//! # use std::process::Command;
|
||||||
|
//! # use std::io::{Read, Write};
|
||||||
|
//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?;
|
||||||
|
//! let (mut pong_rx, pong_tx) = std::pipe::pipe()?;
|
||||||
|
//!
|
||||||
|
//! // Spawn a process that echoes its input.
|
||||||
|
//! let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
|
||||||
|
//!
|
||||||
|
//! ping_tx.write_all(b"hello")?;
|
||||||
|
//! // Close to unblock echo_server's reader.
|
||||||
|
//! drop(ping_tx);
|
||||||
|
//!
|
||||||
|
//! let mut buf = String::new();
|
||||||
|
//! // Block until echo_server's writer is closed.
|
||||||
|
//! pong_rx.read_to_string(&mut buf)?;
|
||||||
|
//! assert_eq!(&buf, "hello");
|
||||||
|
//!
|
||||||
|
//! echo_server.wait()?;
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
//! [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
|
||||||
|
//! [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
|
||||||
|
//! [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
|
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
|
||||||
|
|
||||||
/// Create anonymous pipe that is close-on-exec and blocking.
|
/// Create anonymous pipe that is close-on-exec and blocking.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// See the [module-level](crate::pipe) documentation for examples.
|
||||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
|
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
|
||||||
|
@ -33,6 +79,58 @@ pub struct PipeWriter(pub(crate) AnonPipe);
|
||||||
|
|
||||||
impl PipeReader {
|
impl PipeReader {
|
||||||
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
|
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// #![feature(anonymous_pipe)]
|
||||||
|
/// # #[cfg(miri)] fn main() {}
|
||||||
|
/// # #[cfg(not(miri))]
|
||||||
|
/// # fn main() -> std::io::Result<()> {
|
||||||
|
/// # use std::fs;
|
||||||
|
/// # use std::io::Write;
|
||||||
|
/// # use std::process::Command;
|
||||||
|
/// const NUM_SLOT: u8 = 2;
|
||||||
|
/// const NUM_PROC: u8 = 5;
|
||||||
|
/// const OUTPUT: &str = "work.txt";
|
||||||
|
///
|
||||||
|
/// let mut jobs = vec![];
|
||||||
|
/// let (reader, mut writer) = std::pipe::pipe()?;
|
||||||
|
///
|
||||||
|
/// // Write NUM_SLOT characters the the pipe.
|
||||||
|
/// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
|
||||||
|
///
|
||||||
|
/// // Spawn several processes that read a character from the pipe, do some work, then
|
||||||
|
/// // write back to the pipe. When the pipe is empty, the processes block, so only
|
||||||
|
/// // NUM_SLOT processes can be working at any given time.
|
||||||
|
/// for _ in 0..NUM_PROC {
|
||||||
|
/// jobs.push(
|
||||||
|
/// Command::new("bash")
|
||||||
|
/// .args(["-c",
|
||||||
|
/// &format!(
|
||||||
|
/// "read -n 1\n\
|
||||||
|
/// echo -n 'x' >> '{OUTPUT}'\n\
|
||||||
|
/// echo -n '|'",
|
||||||
|
/// ),
|
||||||
|
/// ])
|
||||||
|
/// .stdin(reader.try_clone()?)
|
||||||
|
/// .stdout(writer.try_clone()?)
|
||||||
|
/// .spawn()?,
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Wait for all jobs to finish.
|
||||||
|
/// for mut job in jobs {
|
||||||
|
/// job.wait()?;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Check our work and clean up.
|
||||||
|
/// let xs = fs::read_to_string(OUTPUT)?;
|
||||||
|
/// fs::remove_file(OUTPUT)?;
|
||||||
|
/// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||||
pub fn try_clone(&self) -> io::Result<Self> {
|
pub fn try_clone(&self) -> io::Result<Self> {
|
||||||
self.0.try_clone().map(Self)
|
self.0.try_clone().map(Self)
|
||||||
|
@ -41,6 +139,38 @@ impl PipeReader {
|
||||||
|
|
||||||
impl PipeWriter {
|
impl PipeWriter {
|
||||||
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
|
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// #![feature(anonymous_pipe)]
|
||||||
|
/// # #[cfg(miri)] fn main() {}
|
||||||
|
/// # #[cfg(not(miri))]
|
||||||
|
/// # fn main() -> std::io::Result<()> {
|
||||||
|
/// # use std::process::Command;
|
||||||
|
/// # use std::io::Read;
|
||||||
|
/// let (mut reader, writer) = std::pipe::pipe()?;
|
||||||
|
///
|
||||||
|
/// // Spawn a process that writes to stdout and stderr.
|
||||||
|
/// let mut peer = Command::new("bash")
|
||||||
|
/// .args([
|
||||||
|
/// "-c",
|
||||||
|
/// "echo -n foo\n\
|
||||||
|
/// echo -n bar >&2"
|
||||||
|
/// ])
|
||||||
|
/// .stdout(writer.try_clone()?)
|
||||||
|
/// .stderr(writer)
|
||||||
|
/// .spawn()?;
|
||||||
|
///
|
||||||
|
/// // Read and check the result.
|
||||||
|
/// let mut msg = String::new();
|
||||||
|
/// reader.read_to_string(&mut msg)?;
|
||||||
|
/// assert_eq!(&msg, "foobar");
|
||||||
|
///
|
||||||
|
/// peer.wait()?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||||
pub fn try_clone(&self) -> io::Result<Self> {
|
pub fn try_clone(&self) -> io::Result<Self> {
|
||||||
self.0.try_clone().map(Self)
|
self.0.try_clone().map(Self)
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
- [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
|
- [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
|
||||||
- [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
|
- [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
|
||||||
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
|
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
|
||||||
|
- [sparcv9-sun-solaris](platform-support/solaris.md)
|
||||||
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
|
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
|
||||||
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
|
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
|
||||||
- [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
|
- [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
|
||||||
|
@ -93,6 +94,7 @@
|
||||||
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
||||||
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
|
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
|
||||||
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
||||||
|
- [x86_64-pc-solaris](platform-support/solaris.md)
|
||||||
- [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
|
- [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
|
||||||
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
|
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
|
||||||
- [xtensa-\*-none-elf](platform-support/xtensa.md)
|
- [xtensa-\*-none-elf](platform-support/xtensa.md)
|
||||||
|
|
|
@ -180,7 +180,7 @@ target | std | notes
|
||||||
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
|
`riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
|
||||||
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
|
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
|
||||||
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
|
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
|
||||||
`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos
|
[`sparcv9-sun-solaris`](platform-support/solaris.md) | ✓ | SPARC V9 Solaris 11.4
|
||||||
[`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M
|
[`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M
|
||||||
[`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M
|
[`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M
|
||||||
[`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat
|
[`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat
|
||||||
|
@ -201,7 +201,7 @@ target | std | notes
|
||||||
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
|
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
|
||||||
[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia
|
[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia
|
||||||
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
|
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
|
||||||
`x86_64-pc-solaris` | ✓ | 64-bit Solaris 11, illumos
|
[`x86_64-pc-solaris`](platform-support/solaris.md) | ✓ | 64-bit x86 Solaris 11.4
|
||||||
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI
|
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI
|
||||||
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
|
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
|
||||||
[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | x86_64 OpenHarmony
|
[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | x86_64 OpenHarmony
|
||||||
|
|
32
src/doc/rustc/src/platform-support/solaris.md
Normal file
32
src/doc/rustc/src/platform-support/solaris.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# sparcv9-sun-solaris
|
||||||
|
# x86_64-pc-solaris
|
||||||
|
|
||||||
|
**Tier: 2**
|
||||||
|
|
||||||
|
Rust for Solaris operating system.
|
||||||
|
|
||||||
|
## Target maintainers
|
||||||
|
|
||||||
|
- Petr Sumbera `sumbera@volny.cz`, https://github.com/psumbera
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Binary built for this target is expected to run on sparcv9 or x86_64, and Solaris 11.4.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
For testing you can download Oracle Solaris 11.4 CBE release from:
|
||||||
|
|
||||||
|
https://www.oracle.com/uk/solaris/solaris11/downloads/solaris-downloads.html
|
||||||
|
|
||||||
|
Solaris CBE release is also available for GitHub CI:
|
||||||
|
|
||||||
|
https://github.com/vmactions/solaris-vm
|
||||||
|
|
||||||
|
Latest Solaris 11.4 SRU can be tested at Compile farm project:
|
||||||
|
|
||||||
|
https://portal.cfarm.net/machines/list/ (cfarm215, cfarm215)
|
||||||
|
|
||||||
|
There are no official Rust binaries for Solaris available for Rustup yet. But you can eventually download unofficial from:
|
||||||
|
|
||||||
|
https://github.com/psumbera/solaris-rust
|
|
@ -42,11 +42,11 @@ LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
|
||||||
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<Rhs> + Sub<Rhs> + Fine<Rhs> {}`
|
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<Rhs> + Sub<Rhs> + Fine<Rhs> {}`
|
||||||
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
|
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
|
||||||
|
|
||||||
error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified
|
error[E0191]: the value of the associated types `Output` in `Div<Rhs>`, `Output` in `Mul<Rhs>` must be specified
|
||||||
--> $DIR/missing-associated-types.rs:20:21
|
--> $DIR/missing-associated-types.rs:20:21
|
||||||
|
|
|
|
||||||
LL | type Bal<Rhs> = dyn X<Rhs>;
|
LL | type Bal<Rhs> = dyn X<Rhs>;
|
||||||
| ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified
|
| ^^^^^^ associated types `Output` (from trait `Div<Rhs>`), `Output` (from trait `Mul<Rhs>`) must be specified
|
||||||
|
|
|
|
||||||
= help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types
|
= help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@ LL | V(x) = func_arg;
|
||||||
| ^^^^ -------- this expression has type `&mut V`
|
| ^^^^ -------- this expression has type `&mut V`
|
||||||
| |
|
| |
|
||||||
| expected `&mut V`, found `V`
|
| expected `&mut V`, found `V`
|
||||||
|
|
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | V(x) = &*func_arg;
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ trait Foo<T> {
|
||||||
trait Cake {}
|
trait Cake {}
|
||||||
impl Cake for () {}
|
impl Cake for () {}
|
||||||
|
|
||||||
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
|
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
|
||||||
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
|
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
|
error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
|
||||||
--> $DIR/assoc_type_bounds.rs:10:16
|
--> $DIR/assoc_type_bounds.rs:10:16
|
||||||
|
|
|
|
||||||
LL | type Bar
|
LL | type Bar
|
||||||
|
@ -7,7 +7,7 @@ LL | type Bar
|
||||||
LL | fn foo(_: &dyn Foo<()>) {}
|
LL | fn foo(_: &dyn Foo<()>) {}
|
||||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
||||||
|
|
||||||
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
|
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||||
--> $DIR/assoc_type_bounds.rs:11:16
|
--> $DIR/assoc_type_bounds.rs:11:16
|
||||||
|
|
|
|
||||||
LL | type Bar
|
LL | type Bar
|
||||||
|
|
|
@ -7,7 +7,7 @@ trait Foo<T> {
|
||||||
trait Cake {}
|
trait Cake {}
|
||||||
impl Cake for () {}
|
impl Cake for () {}
|
||||||
|
|
||||||
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
|
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
|
||||||
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
|
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
|
error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
|
||||||
--> $DIR/assoc_type_bounds2.rs:10:16
|
--> $DIR/assoc_type_bounds2.rs:10:16
|
||||||
|
|
|
|
||||||
LL | type Bar
|
LL | type Bar
|
||||||
|
@ -7,7 +7,7 @@ LL | type Bar
|
||||||
LL | fn foo(_: &dyn Foo<()>) {}
|
LL | fn foo(_: &dyn Foo<()>) {}
|
||||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
||||||
|
|
||||||
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
|
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||||
--> $DIR/assoc_type_bounds2.rs:11:16
|
--> $DIR/assoc_type_bounds2.rs:11:16
|
||||||
|
|
|
|
||||||
LL | type Bar
|
LL | type Bar
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
trait Sup<T> {
|
||||||
|
type Assoc: Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Sup<T> for () {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
impl<T: Default, U: Default> Dyn<T, U> for () {}
|
||||||
|
|
||||||
|
trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B> {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
|
||||||
|
//~^ ERROR the value of the associated type `Assoc` in `Sup<u32>` must be specified
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0191]: the value of the associated type `Assoc` in `Sup<u32>` must be specified
|
||||||
|
--> $DIR/require-assoc-for-all-super-substs.rs:13:17
|
||||||
|
|
|
||||||
|
LL | type Assoc: Default;
|
||||||
|
| ------------------- `Assoc` defined here
|
||||||
|
...
|
||||||
|
LL | let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
|
||||||
|
| ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = Type>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0191`.
|
|
@ -12,7 +12,7 @@ help: if this is a dyn-compatible trait, use `dyn`
|
||||||
LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
|
LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
|
||||||
| ++++ +
|
| ++++ +
|
||||||
|
|
||||||
error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
|
error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
|
||||||
--> $DIR/issue-28344.rs:4:17
|
--> $DIR/issue-28344.rs:4:17
|
||||||
|
|
|
|
||||||
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
|
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
|
||||||
|
@ -31,7 +31,7 @@ help: if this is a dyn-compatible trait, use `dyn`
|
||||||
LL | let g = <dyn BitXor>::bitor;
|
LL | let g = <dyn BitXor>::bitor;
|
||||||
| ++++ +
|
| ++++ +
|
||||||
|
|
||||||
error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
|
error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
|
||||||
--> $DIR/issue-28344.rs:9:13
|
--> $DIR/issue-28344.rs:9:13
|
||||||
|
|
|
|
||||||
LL | let g = BitXor::bitor;
|
LL | let g = BitXor::bitor;
|
||||||
|
|
|
@ -2,57 +2,61 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/issue-57741.rs:20:9
|
--> $DIR/issue-57741.rs:20:9
|
||||||
|
|
|
|
||||||
LL | let y = match x {
|
LL | let y = match x {
|
||||||
| -
|
| - this expression has type `Box<T>`
|
||||||
| |
|
|
||||||
| this expression has type `Box<T>`
|
|
||||||
| help: consider dereferencing the boxed value: `*x`
|
|
||||||
LL | T::A(a) | T::B(a) => a,
|
LL | T::A(a) | T::B(a) => a,
|
||||||
| ^^^^^^^ expected `Box<T>`, found `T`
|
| ^^^^^^^ expected `Box<T>`, found `T`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<T>`
|
= note: expected struct `Box<T>`
|
||||||
found enum `T`
|
found enum `T`
|
||||||
|
help: consider dereferencing the boxed value
|
||||||
|
|
|
||||||
|
LL | let y = match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-57741.rs:20:19
|
--> $DIR/issue-57741.rs:20:19
|
||||||
|
|
|
|
||||||
LL | let y = match x {
|
LL | let y = match x {
|
||||||
| -
|
| - this expression has type `Box<T>`
|
||||||
| |
|
|
||||||
| this expression has type `Box<T>`
|
|
||||||
| help: consider dereferencing the boxed value: `*x`
|
|
||||||
LL | T::A(a) | T::B(a) => a,
|
LL | T::A(a) | T::B(a) => a,
|
||||||
| ^^^^^^^ expected `Box<T>`, found `T`
|
| ^^^^^^^ expected `Box<T>`, found `T`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<T>`
|
= note: expected struct `Box<T>`
|
||||||
found enum `T`
|
found enum `T`
|
||||||
|
help: consider dereferencing the boxed value
|
||||||
|
|
|
||||||
|
LL | let y = match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-57741.rs:27:9
|
--> $DIR/issue-57741.rs:27:9
|
||||||
|
|
|
|
||||||
LL | let y = match x {
|
LL | let y = match x {
|
||||||
| -
|
| - this expression has type `Box<S>`
|
||||||
| |
|
|
||||||
| this expression has type `Box<S>`
|
|
||||||
| help: consider dereferencing the boxed value: `*x`
|
|
||||||
LL | S::A { a } | S::B { b: a } => a,
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
| ^^^^^^^^^^ expected `Box<S>`, found `S`
|
| ^^^^^^^^^^ expected `Box<S>`, found `S`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<S>`
|
= note: expected struct `Box<S>`
|
||||||
found enum `S`
|
found enum `S`
|
||||||
|
help: consider dereferencing the boxed value
|
||||||
|
|
|
||||||
|
LL | let y = match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-57741.rs:27:22
|
--> $DIR/issue-57741.rs:27:22
|
||||||
|
|
|
|
||||||
LL | let y = match x {
|
LL | let y = match x {
|
||||||
| -
|
| - this expression has type `Box<S>`
|
||||||
| |
|
|
||||||
| this expression has type `Box<S>`
|
|
||||||
| help: consider dereferencing the boxed value: `*x`
|
|
||||||
LL | S::A { a } | S::B { b: a } => a,
|
LL | S::A { a } | S::B { b: a } => a,
|
||||||
| ^^^^^^^^^^^^^ expected `Box<S>`, found `S`
|
| ^^^^^^^^^^^^^ expected `Box<S>`, found `S`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<S>`
|
= note: expected struct `Box<S>`
|
||||||
found enum `S`
|
found enum `S`
|
||||||
|
help: consider dereferencing the boxed value
|
||||||
|
|
|
||||||
|
LL | let y = match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@ LL | let Bar::Present(z) = self else {
|
||||||
| ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo`
|
| ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo`
|
||||||
| |
|
| |
|
||||||
| expected `Foo`, found `Bar`
|
| expected `Foo`, found `Bar`
|
||||||
|
|
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | let Bar::Present(z) = &**self else {
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/let-else-deref-coercion.rs:68:13
|
--> $DIR/let-else-deref-coercion.rs:68:13
|
||||||
|
@ -13,6 +18,11 @@ LL | let Bar(z) = x;
|
||||||
| ^^^^^^ - this expression has type `&mut irrefutable::Foo`
|
| ^^^^^^ - this expression has type `&mut irrefutable::Foo`
|
||||||
| |
|
| |
|
||||||
| expected `Foo`, found `Bar`
|
| expected `Foo`, found `Bar`
|
||||||
|
|
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | let Bar(z) = &**x;
|
||||||
|
| ~~~~
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
13
tests/ui/self/arbitrary_self_types_nonnull.rs
Normal file
13
tests/ui/self/arbitrary_self_types_nonnull.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn m(self: std::ptr::NonNull<Self>) {}
|
||||||
|
//~^ ERROR: invalid `self` parameter type
|
||||||
|
fn n(self: &std::ptr::NonNull<Self>) {}
|
||||||
|
//~^ ERROR: invalid `self` parameter type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
23
tests/ui/self/arbitrary_self_types_nonnull.stderr
Normal file
23
tests/ui/self/arbitrary_self_types_nonnull.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error[E0307]: invalid `self` parameter type: `NonNull<A>`
|
||||||
|
--> $DIR/arbitrary_self_types_nonnull.rs:6:16
|
||||||
|
|
|
||||||
|
LL | fn m(self: std::ptr::NonNull<Self>) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: type of `self` must be `Self` or some type implementing `Receiver`
|
||||||
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
= note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
|
error[E0307]: invalid `self` parameter type: `&NonNull<A>`
|
||||||
|
--> $DIR/arbitrary_self_types_nonnull.rs:8:16
|
||||||
|
|
|
||||||
|
LL | fn n(self: &std::ptr::NonNull<Self>) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: type of `self` must be `Self` or some type implementing `Receiver`
|
||||||
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
= note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0307`.
|
13
tests/ui/self/arbitrary_self_types_weak.rs
Normal file
13
tests/ui/self/arbitrary_self_types_weak.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
fn m(self: std::rc::Weak<Self>) {}
|
||||||
|
//~^ ERROR: invalid `self` parameter type
|
||||||
|
fn n(self: std::sync::Weak<Self>) {}
|
||||||
|
//~^ ERROR: invalid `self` parameter type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
23
tests/ui/self/arbitrary_self_types_weak.stderr
Normal file
23
tests/ui/self/arbitrary_self_types_weak.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error[E0307]: invalid `self` parameter type: `std::rc::Weak<A>`
|
||||||
|
--> $DIR/arbitrary_self_types_weak.rs:6:16
|
||||||
|
|
|
||||||
|
LL | fn m(self: std::rc::Weak<Self>) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: type of `self` must be `Self` or some type implementing `Receiver`
|
||||||
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
= note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
|
error[E0307]: invalid `self` parameter type: `std::sync::Weak<A>`
|
||||||
|
--> $DIR/arbitrary_self_types_weak.rs:8:16
|
||||||
|
|
|
||||||
|
LL | fn n(self: std::sync::Weak<Self>) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: type of `self` must be `Self` or some type implementing `Receiver`
|
||||||
|
= help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
|
||||||
|
= note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0307`.
|
84
tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs
Normal file
84
tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
fn main() {
|
||||||
|
let mut x = Arc::new(Some(1));
|
||||||
|
match x {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
match &x {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut y = Box::new(Some(1));
|
||||||
|
match y {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut z = Arc::new(Some(1));
|
||||||
|
match z as Arc<Option<i32>> {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
let z_const: &Arc<Option<i32>> = &z;
|
||||||
|
match z_const {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal reference because Arc doesn't implement DerefMut.
|
||||||
|
let z_mut: &mut Arc<Option<i32>> = &mut z;
|
||||||
|
match z_mut {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutable reference because Box does implement DerefMut.
|
||||||
|
let y_mut: &mut Box<Option<i32>> = &mut y;
|
||||||
|
match y_mut {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difficult expression.
|
||||||
|
let difficult = Arc::new(Some(1));
|
||||||
|
match (& (&difficult) ) {
|
||||||
|
//~^ HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
//~| HELP consider dereferencing to access the inner value using the Deref trait
|
||||||
|
Some(_) => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
None => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
259
tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr
Normal file
259
tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:7:9
|
||||||
|
|
|
||||||
|
LL | match x {
|
||||||
|
| - this expression has type `Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:9:9
|
||||||
|
|
|
||||||
|
LL | match x {
|
||||||
|
| - this expression has type `Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *x {
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:16:9
|
||||||
|
|
|
||||||
|
LL | match &x {
|
||||||
|
| -- this expression has type `&Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &*x {
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:18:9
|
||||||
|
|
|
||||||
|
LL | match &x {
|
||||||
|
| -- this expression has type `&Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &*x {
|
||||||
|
| ~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:26:9
|
||||||
|
|
|
||||||
|
LL | match y {
|
||||||
|
| - this expression has type `Box<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Box<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Box<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *y {
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:28:9
|
||||||
|
|
|
||||||
|
LL | match y {
|
||||||
|
| - this expression has type `Box<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Box<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Box<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *y {
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:36:9
|
||||||
|
|
|
||||||
|
LL | match z as Arc<Option<i32>> {
|
||||||
|
| --------------------- this expression has type `Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *(z as Arc<Option<i32>>) {
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:38:9
|
||||||
|
|
|
||||||
|
LL | match z as Arc<Option<i32>> {
|
||||||
|
| --------------------- this expression has type `Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match *(z as Arc<Option<i32>>) {
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:46:9
|
||||||
|
|
|
||||||
|
LL | match z_const {
|
||||||
|
| ------- this expression has type `&Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**z_const {
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:48:9
|
||||||
|
|
|
||||||
|
LL | match z_const {
|
||||||
|
| ------- this expression has type `&Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**z_const {
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:57:9
|
||||||
|
|
|
||||||
|
LL | match z_mut {
|
||||||
|
| ----- this expression has type `&mut Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**z_mut {
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:59:9
|
||||||
|
|
|
||||||
|
LL | match z_mut {
|
||||||
|
| ----- this expression has type `&mut Arc<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**z_mut {
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:68:9
|
||||||
|
|
|
||||||
|
LL | match y_mut {
|
||||||
|
| ----- this expression has type `&mut Box<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Box<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Box<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**y_mut {
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:70:9
|
||||||
|
|
|
||||||
|
LL | match y_mut {
|
||||||
|
| ----- this expression has type `&mut Box<Option<i32>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Box<Option<i32>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Box<Option<i32>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &**y_mut {
|
||||||
|
| ~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:79:9
|
||||||
|
|
|
||||||
|
LL | match (& (&difficult) ) {
|
||||||
|
| ------------------ this expression has type `&&Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | Some(_) => {}
|
||||||
|
| ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &*difficult {
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-deref-in-match-issue-132784.rs:81:9
|
||||||
|
|
|
||||||
|
LL | match (& (&difficult) ) {
|
||||||
|
| ------------------ this expression has type `&&Arc<Option<{integer}>>`
|
||||||
|
...
|
||||||
|
LL | None => {}
|
||||||
|
| ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
|
||||||
|
|
|
||||||
|
= note: expected struct `Arc<Option<{integer}>>`
|
||||||
|
found enum `Option<_>`
|
||||||
|
help: consider dereferencing to access the inner value using the Deref trait
|
||||||
|
|
|
||||||
|
LL | match &*difficult {
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 16 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Reference in a new issue