Auto merge of #129595 - matthiaskrgr:rollup-4udn7nn, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #129288 (Use subtyping for `UnsafeFnPointer` coercion, too)
 - #129405 (Fixing span manipulation and indentation of the suggestion introduced by #126187)
 - #129518 (gitignore: ignore ICE reports regardless of directory)
 - #129519 (Remove redundant flags from `lower_ty_common` that can be inferred from the HIR)
 - #129525 (rustdoc: clean up tuple <-> primitive conversion docs)
 - #129526 (Use `FxHasher` on new solver unconditionally)
 - #129544 (Removes dead code from the compiler)
 - #129553 (add back test for stable-const-can-only-call-stable-const)
 - #129590 (Avoid taking reference of &TyKind)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-08-26 05:45:40 +00:00
commit f48062e7d0
44 changed files with 283 additions and 192 deletions

4
.gitignore vendored
View File

@ -56,7 +56,9 @@ build/
/src/tools/x/target /src/tools/x/target
# Created by default with `src/ci/docker/run.sh` # Created by default with `src/ci/docker/run.sh`
/obj/ /obj/
/rustc-ice*
## ICE reports
rustc-ice-*.txt
## Temporary files ## Temporary files
*~ *~

View File

@ -4536,6 +4536,7 @@ dependencies = [
"bitflags 2.6.0", "bitflags 2.6.0",
"derive-where", "derive-where",
"indexmap", "indexmap",
"rustc-hash",
"rustc_ast_ir", "rustc_ast_ir",
"rustc_data_structures", "rustc_data_structures",
"rustc_index", "rustc_index",

View File

@ -290,7 +290,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
ty: Ty<'_>, ty: Ty<'_>,
is_index: Option<bool>, is_index: Option<bool>,
) -> Diag<'infcx> { ) -> Diag<'infcx> {
let type_name = match (&ty.kind(), is_index) { let type_name = match (ty.kind(), is_index) {
(&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
(&ty::Slice(_), _) => "slice", (&ty::Slice(_), _) => "slice",
_ => span_bug!(move_from_span, "this path should not cause illegal move"), _ => span_bug!(move_from_span, "this path should not cause illegal move"),

View File

@ -201,7 +201,7 @@ fn place_components_conflict<'tcx>(
let base_ty = base.ty(body, tcx).ty; let base_ty = base.ty(body, tcx).ty;
match (elem, &base_ty.kind(), access) { match (elem, base_ty.kind(), access) {
(_, _, Shallow(Some(ArtificialField::ArrayLength))) (_, _, Shallow(Some(ArtificialField::ArrayLength)))
| (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => {
// The array length is like additional fields on the // The array length is like additional fields on the

View File

@ -2043,9 +2043,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
if let Err(terr) = self.eq_types( if let Err(terr) = self.sub_types(
*ty,
ty_fn_ptr_from, ty_fn_ptr_from,
*ty,
location.to_locations(), location.to_locations(),
ConstraintCategory::Cast { unsize_to: None }, ConstraintCategory::Cast { unsize_to: None },
) { ) {

View File

@ -419,7 +419,7 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
const_eval_unstable_in_stable = const_eval_unstable_in_stable =
const-stable function cannot use `#[feature({$gate})]` const-stable function cannot use `#[feature({$gate})]`
.unstable_sugg = if it is not part of the public API, make this function unstably const .unstable_sugg = if it is not part of the public API, make this function unstably const
.bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
const_eval_unterminated_c_string = const_eval_unterminated_c_string =
reading a null-terminated string starting at {$pointer} with no null found before end of allocation reading a null-terminated string starting at {$pointer} with no null found before end of allocation

View File

@ -388,7 +388,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (src_pointee_ty, dest_pointee_ty) = let (src_pointee_ty, dest_pointee_ty) =
self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env);
match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { match (src_pointee_ty.kind(), dest_pointee_ty.kind()) {
(&ty::Array(_, length), &ty::Slice(_)) => { (&ty::Array(_, length), &ty::Slice(_)) => {
let ptr = self.read_pointer(src)?; let ptr = self.read_pointer(src)?;
let val = Immediate::new_slice( let val = Immediate::new_slice(
@ -478,9 +478,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
dest: &PlaceTy<'tcx, M::Provenance>, dest: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty);
match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { match (src.layout.ty.kind(), cast_ty.ty.kind()) {
(&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _)) (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _))
| (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, *s, *c), | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c),
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b); // implies same number of fields assert_eq!(def_a, def_b); // implies same number of fields

View File

@ -392,7 +392,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
} }
fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
if let RegionInferReason::BorrowedObjectLifetimeDefault = reason { if let RegionInferReason::ObjectLifetimeDefault = reason {
let e = struct_span_code_err!( let e = struct_span_code_err!(
self.dcx(), self.dcx(),
span, span,

View File

@ -608,7 +608,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
match &self_ty.kind() { match self_ty.kind() {
// Point at the type that couldn't satisfy the bound. // Point at the type that couldn't satisfy the bound.
ty::Adt(def, _) => { ty::Adt(def, _) => {
bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)

View File

@ -15,11 +15,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// ///
/// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
/// In edition 2021 and onward we emit a hard error for them. /// In edition 2021 and onward we emit a hard error for them.
pub(super) fn prohibit_or_lint_bare_trait_object_ty( pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) {
&self,
self_ty: &hir::Ty<'_>,
in_path: bool,
) {
let tcx = self.tcx(); let tcx = self.tcx();
let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
@ -28,6 +24,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
return; return;
}; };
let in_path = match tcx.parent_hir_node(self_ty.hir_id) {
hir::Node::Ty(hir::Ty {
kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)),
..
})
| hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
..
})
| hir::Node::Pat(hir::Pat {
kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)),
..
}) if qself.hir_id == self_ty.hir_id => true,
_ => false,
};
let needs_bracket = in_path let needs_bracket = in_path
&& !tcx && !tcx
.sess .sess

View File

@ -85,10 +85,9 @@ pub enum PredicateFilter {
#[derive(Debug)] #[derive(Debug)]
pub enum RegionInferReason<'a> { pub enum RegionInferReason<'a> {
/// Lifetime on a trait object behind a reference. /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`.
/// This allows inferring information from the reference. ExplicitObjectLifetime,
BorrowedObjectLifetimeDefault, /// A trait object's lifetime when it is elided, e.g. `dyn Any`.
/// A trait object's lifetime.
ObjectLifetimeDefault, ObjectLifetimeDefault,
/// Generic lifetime parameter /// Generic lifetime parameter
Param(&'a ty::GenericParamDef), Param(&'a ty::GenericParamDef),
@ -1057,7 +1056,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Find the type of the associated item, and the trait where the associated // Find the type of the associated item, and the trait where the associated
// item is declared. // item is declared.
let bound = match (&qself_ty.kind(), qself_res) { let bound = match (qself_ty.kind(), qself_res) {
(_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
// `Self` in an impl of a trait -- we have a concrete self type and a // `Self` in an impl of a trait -- we have a concrete self type and a
// trait reference. // trait reference.
@ -1999,16 +1998,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} }
} }
/// Lower a type from the HIR to our internal notion of a type.
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
self.lower_ty_common(hir_ty, false, false)
}
/// Lower a type inside of a path from the HIR to our internal notion of a type.
pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
self.lower_ty_common(hir_ty, false, true)
}
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
match idx { match idx {
@ -2026,7 +2015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// 2. `in_path`: Whether the type appears inside of a path. /// 2. `in_path`: Whether the type appears inside of a path.
/// Used to provide correct diagnostics for bare trait object types. /// Used to provide correct diagnostics for bare trait object types.
#[instrument(level = "debug", skip(self), ret)] #[instrument(level = "debug", skip(self), ret)]
fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> { pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
let result_ty = match &hir_ty.kind { let result_ty = match &hir_ty.kind {
@ -2036,7 +2025,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::TyKind::Ref(region, mt) => { hir::TyKind::Ref(region, mt) => {
let r = self.lower_lifetime(region, RegionInferReason::Reference); let r = self.lower_lifetime(region, RegionInferReason::Reference);
debug!(?r); debug!(?r);
let t = self.lower_ty_common(mt.ty, true, false); let t = self.lower_ty(mt.ty);
Ty::new_ref(tcx, r, t, mt.mutbl) Ty::new_ref(tcx, r, t, mt.mutbl)
} }
hir::TyKind::Never => tcx.types.never, hir::TyKind::Never => tcx.types.never,
@ -2065,20 +2054,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
) )
} }
hir::TyKind::TraitObject(bounds, lifetime, repr) => { hir::TyKind::TraitObject(bounds, lifetime, repr) => {
self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); self.prohibit_or_lint_bare_trait_object_ty(hir_ty);
let repr = match repr { let repr = match repr {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar, TraitObjectSyntax::DynStar => ty::DynStar,
}; };
self.lower_trait_object_ty( self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
hir_ty.span,
hir_ty.hir_id,
bounds,
lifetime,
borrowed,
repr,
)
} }
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path); debug!(?maybe_qself, ?path);
@ -2106,7 +2088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} }
hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => { hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
debug!(?qself, ?segment); debug!(?qself, ?segment);
let ty = self.lower_ty_common(qself, false, true); let ty = self.lower_ty(qself);
self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false) self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false)
.map(|(ty, _, _)| ty) .map(|(ty, _, _)| ty)
.unwrap_or_else(|guar| Ty::new_error(tcx, guar)) .unwrap_or_else(|guar| Ty::new_error(tcx, guar))

View File

@ -30,7 +30,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir_id: hir::HirId, hir_id: hir::HirId,
hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
lifetime: &hir::Lifetime, lifetime: &hir::Lifetime,
borrowed: bool,
representation: DynKind, representation: DynKind,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
@ -325,22 +324,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
v.dedup(); v.dedup();
let existential_predicates = tcx.mk_poly_existential_predicates(&v); let existential_predicates = tcx.mk_poly_existential_predicates(&v);
// Use explicitly-specified region bound. // Use explicitly-specified region bound, unless the bound is missing.
let region_bound = if !lifetime.is_elided() { let region_bound = if !lifetime.is_elided() {
self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
} else { } else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
// Curiously, we prefer object lifetime default for `+ '_`...
if tcx.named_bound_var(lifetime.hir_id).is_some() { if tcx.named_bound_var(lifetime.hir_id).is_some() {
self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
} else { } else {
self.re_infer( let reason =
span, if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res {
if borrowed { if let hir::Node::Ty(hir::Ty {
RegionInferReason::ObjectLifetimeDefault kind: hir::TyKind::Ref(parent_lifetime, _),
..
}) = tcx.parent_hir_node(hir_id)
&& tcx.named_bound_var(parent_lifetime.hir_id).is_none()
{
// Parent lifetime must have failed to resolve. Don't emit a redundant error.
RegionInferReason::ExplicitObjectLifetime
} else {
RegionInferReason::ObjectLifetimeDefault
}
} else { } else {
RegionInferReason::BorrowedObjectLifetimeDefault RegionInferReason::ExplicitObjectLifetime
}, };
) self.re_infer(span, reason)
} }
}) })
}; };

View File

@ -798,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// to be object-safe. // to be object-safe.
// We manually call `register_wf_obligation` in the success path // We manually call `register_wf_obligation` in the success path
// below. // below.
let ty = self.lowerer().lower_ty_in_path(qself); let ty = self.lowerer().lower_ty(qself);
(LoweredTy::from_raw(self, span, ty), qself, segment) (LoweredTy::from_raw(self, span, ty), qself, segment)
} }
QPath::LangItem(..) => { QPath::LangItem(..) => {

View File

@ -2975,7 +2975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut suffix_suggestion = sugg.clone(); let mut suffix_suggestion = sugg.clone();
suffix_suggestion.push(( suffix_suggestion.push((
if matches!( if matches!(
(&expected_ty.kind(), &checked_ty.kind()), (expected_ty.kind(), checked_ty.kind()),
(ty::Int(_) | ty::Uint(_), ty::Float(_)) (ty::Int(_) | ty::Uint(_), ty::Float(_))
) { ) {
// Remove fractional part from literal, for example `42.0f32` into `42` // Remove fractional part from literal, for example `42.0f32` into `42`
@ -3077,7 +3077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable);
}; };
match (&expected_ty.kind(), &checked_ty.kind()) { match (expected_ty.kind(), checked_ty.kind()) {
(ty::Int(exp), ty::Int(found)) => { (ty::Int(exp), ty::Int(found)) => {
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
{ {

View File

@ -1012,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
match &self_ty.kind() { match self_ty.kind() {
// Point at the type that couldn't satisfy the bound. // Point at the type that couldn't satisfy the bound.
ty::Adt(def, _) => { ty::Adt(def, _) => {
bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)

View File

@ -1336,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// More generally, the expected type wants a tuple variant with one field of an // More generally, the expected type wants a tuple variant with one field of an
// N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
// with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
let missing_parentheses = match (&expected.kind(), fields, had_err) { let missing_parentheses = match (expected.kind(), fields, had_err) {
// #67037: only do this if we could successfully type-check the expected type against // #67037: only do this if we could successfully type-check the expected type against
// the tuple struct pattern. Otherwise the args could get out of range on e.g., // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
// `let P() = U;` where `P != U` with `struct P<T>(T);`. // `let P() = U;` where `P != U` with `struct P<T>(T);`.

View File

@ -99,6 +99,4 @@ incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
incremental_write_new = failed to write {$name} to `{$path}`: {$err} incremental_write_new = failed to write {$name} to `{$path}`: {$err}

View File

@ -272,13 +272,6 @@ pub struct LoadDepGraph {
pub err: std::io::Error, pub err: std::io::Error,
} }
#[derive(Diagnostic)]
#[diag(incremental_write_dep_graph)]
pub struct WriteDepGraph<'a> {
pub path: &'a Path,
pub err: std::io::Error,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(incremental_move_dep_graph)] #[diag(incremental_move_dep_graph)]
pub struct MoveDepGraph<'a> { pub struct MoveDepGraph<'a> {

View File

@ -1104,7 +1104,7 @@ where
} }
fn is_never(this: TyAndLayout<'tcx>) -> bool { fn is_never(this: TyAndLayout<'tcx>) -> bool {
this.ty.kind() == &ty::Never matches!(this.ty.kind(), ty::Never)
} }
fn is_tuple(this: TyAndLayout<'tcx>) -> bool { fn is_tuple(this: TyAndLayout<'tcx>) -> bool {

View File

@ -296,7 +296,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> (Ty<'tcx>, Ty<'tcx>) { ) -> (Ty<'tcx>, Ty<'tcx>) {
let (mut a, mut b) = (source, target); let (mut a, mut b) = (source, target);
loop { loop {
match (&a.kind(), &b.kind()) { match (a.kind(), b.kind()) {
(&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args))
if a_def == b_def && a_def.is_struct() => if a_def == b_def && a_def.is_struct() =>
{ {

View File

@ -127,7 +127,7 @@ fn lit_to_mir_constant<'tcx>(
Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
}; };
let value = match (lit, &ty.kind()) { let value = match (lit, ty.kind()) {
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
let s = s.as_str(); let s = s.as_str();
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());

View File

@ -29,7 +29,7 @@ pub(crate) fn lit_to_const<'tcx>(
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))) .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)))
}; };
let valtree = match (lit, &ty.kind()) { let valtree = match (lit, ty.kind()) {
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
let str_bytes = s.as_str().as_bytes(); let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes) ty::ValTree::from_raw_bytes(tcx, str_bytes)

View File

@ -1035,9 +1035,9 @@ fn find_vtable_types_for_unsizing<'tcx>(
} }
}; };
match (&source_ty.kind(), &target_ty.kind()) { match (source_ty.kind(), target_ty.kind()) {
(&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
| (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(*a, *b), | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b),
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
} }

View File

@ -481,10 +481,6 @@ passes_must_not_suspend =
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait `must_not_suspend` attribute should be applied to a struct, enum, union, or trait
.label = is not a struct, enum, union, or trait .label = is not a struct, enum, union, or trait
passes_must_use_async =
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
passes_must_use_no_effect = passes_must_use_no_effect =
`#[must_use]` has no effect when applied to {$article} {$target} `#[must_use]` has no effect when applied to {$article} {$target}

View File

@ -952,6 +952,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
bare_fn_ty.decl.inputs.len() == 1 bare_fn_ty.decl.inputs.len() == 1
} else { } else {
false false
}
|| if let Some(&[hir::GenericArg::Type(ty)]) = i
.of_trait
.as_ref()
.and_then(|trait_ref| trait_ref.path.segments.last())
.map(|last_segment| last_segment.args().args)
{
matches!(&ty.kind, hir::TyKind::Tup([_]))
} else {
false
}; };
if !is_valid { if !is_valid {
self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() }); self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });

View File

@ -371,13 +371,6 @@ pub struct FfiConstInvalidTarget {
pub attr_span: Span, pub attr_span: Span,
} }
#[derive(LintDiagnostic)]
#[diag(passes_must_use_async)]
pub struct MustUseAsync {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(passes_must_use_no_effect)] #[diag(passes_must_use_no_effect)]
pub struct MustUseNoEffect { pub struct MustUseNoEffect {

View File

@ -382,7 +382,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if !expected_inner.is_fn() || !found_inner.is_fn() { if !expected_inner.is_fn() || !found_inner.is_fn() {
return; return;
} }
match (&expected_inner.kind(), &found_inner.kind()) { match (expected_inner.kind(), found_inner.kind()) {
(ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => { (ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => {
let sig = sig_tys.with(*hdr); let sig = sig_tys.with(*hdr);
let expected_sig = &(self.normalize_fn_sig)(sig); let expected_sig = &(self.normalize_fn_sig)(sig);

View File

@ -4702,10 +4702,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let hir::ExprKind::Block(b, _) = body.value.kind if let hir::ExprKind::Block(b, _) = body.value.kind
&& b.expr.is_none() && b.expr.is_none()
{ {
// The span of '}' in the end of block.
let span = self.tcx.sess.source_map().end_point(b.span);
sugg_spans.push(( sugg_spans.push((
// The span will point to the closing curly brace `}` of the block. span.shrink_to_lo(),
b.span.shrink_to_hi().with_lo(b.span.hi() - BytePos(1)), format!(
"\n Ok(())\n}".to_string(), "{}{}",
" Ok(())\n",
self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(),
),
)); ));
} }
err.multipart_suggestion_verbose( err.multipart_suggestion_verbose(

View File

@ -4,7 +4,6 @@ use crate::layout;
pub(crate) trait QueryContext { pub(crate) trait QueryContext {
type Def: layout::Def; type Def: layout::Def;
type Ref: layout::Ref; type Ref: layout::Ref;
type Scope: Copy;
} }
#[cfg(test)] #[cfg(test)]
@ -28,20 +27,17 @@ pub(crate) mod test {
impl QueryContext for UltraMinimal { impl QueryContext for UltraMinimal {
type Def = Def; type Def = Def;
type Ref = !; type Ref = !;
type Scope = ();
} }
} }
#[cfg(feature = "rustc")] #[cfg(feature = "rustc")]
mod rustc { mod rustc {
use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::ty::TyCtxt;
use super::*; use super::*;
impl<'tcx> super::QueryContext for TyCtxt<'tcx> { impl<'tcx> super::QueryContext for TyCtxt<'tcx> {
type Def = layout::rustc::Def<'tcx>; type Def = layout::rustc::Def<'tcx>;
type Ref = layout::rustc::Ref<'tcx>; type Ref = layout::rustc::Ref<'tcx>;
type Scope = Ty<'tcx>;
} }
} }

View File

@ -8,6 +8,7 @@ edition = "2021"
bitflags = "2.4.1" bitflags = "2.4.1"
derive-where = "1.2.7" derive-where = "1.2.7"
indexmap = "2.0.0" indexmap = "2.0.0"
rustc-hash = "1.1.0"
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index", default-features = false } rustc_index = { path = "../rustc_index", default-features = false }

View File

@ -1,8 +1,13 @@
use std::hash::BuildHasherDefault;
use rustc_hash::FxHasher;
pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
pub type IndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
mod impl_ { mod impl_ {
pub use rustc_data_structures::fx::{
FxHashMap as HashMap, FxHashSet as HashSet, FxIndexMap as IndexMap, FxIndexSet as IndexSet,
};
pub use rustc_data_structures::sso::{SsoHashMap, SsoHashSet}; pub use rustc_data_structures::sso::{SsoHashMap, SsoHashSet};
pub use rustc_data_structures::stack::ensure_sufficient_stack; pub use rustc_data_structures::stack::ensure_sufficient_stack;
pub use rustc_data_structures::sync::Lrc; pub use rustc_data_structures::sync::Lrc;
@ -10,11 +15,9 @@ mod impl_ {
#[cfg(not(feature = "nightly"))] #[cfg(not(feature = "nightly"))]
mod impl_ { mod impl_ {
pub use std::collections::{HashMap, HashMap as SsoHashMap, HashSet, HashSet as SsoHashSet}; pub use std::collections::{HashMap as SsoHashMap, HashSet as SsoHashSet};
pub use std::sync::Arc as Lrc; pub use std::sync::Arc as Lrc;
pub use indexmap::{IndexMap, IndexSet};
#[inline] #[inline]
pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R { pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
f() f()

View File

@ -59,6 +59,7 @@ fn box_deref_lval() {
assert_eq!(x.get(), 1000); assert_eq!(x.get(), 1000);
} }
#[allow(unused)]
pub struct ConstAllocator; pub struct ConstAllocator;
unsafe impl Allocator for ConstAllocator { unsafe impl Allocator for ConstAllocator {

View File

@ -122,23 +122,29 @@ macro_rules! tuple_impls {
} }
} }
#[stable(feature = "array_tuple_conv", since = "1.71.0")] maybe_tuple_doc! {
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { $($T)+ @
#[inline] #[stable(feature = "array_tuple_conv", since = "1.71.0")]
#[allow(non_snake_case)] impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
fn from(array: [T; ${count($T)}]) -> Self { #[inline]
let [$($T,)+] = array; #[allow(non_snake_case)]
($($T,)+) fn from(array: [T; ${count($T)}]) -> Self {
let [$($T,)+] = array;
($($T,)+)
}
} }
} }
#[stable(feature = "array_tuple_conv", since = "1.71.0")] maybe_tuple_doc! {
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { $($T)+ @
#[inline] #[stable(feature = "array_tuple_conv", since = "1.71.0")]
#[allow(non_snake_case)] impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { #[inline]
let ($($T,)+) = tuple; #[allow(non_snake_case)]
[$($T,)+] fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
let ($($T,)+) = tuple;
[$($T,)+]
}
} }
} }
} }
@ -148,7 +154,7 @@ macro_rules! tuple_impls {
// Otherwise, it hides the docs entirely. // Otherwise, it hides the docs entirely.
macro_rules! maybe_tuple_doc { macro_rules! maybe_tuple_doc {
($a:ident @ #[$meta:meta] $item:item) => { ($a:ident @ #[$meta:meta] $item:item) => {
#[doc(fake_variadic)] #[cfg_attr(not(bootstrap), doc(fake_variadic))]
#[doc = "This trait is implemented for tuples up to twelve items long."] #[doc = "This trait is implemented for tuples up to twelve items long."]
#[$meta] #[$meta]
$item $item

View File

@ -1288,56 +1288,90 @@ impl clean::Impl {
if self.is_negative_trait_impl() { if self.is_negative_trait_impl() {
write!(f, "!")?; write!(f, "!")?;
} }
ty.print(cx).fmt(f)?; if self.kind.is_fake_variadic()
&& let generics = ty.generics()
&& let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
{
let last = ty.last();
if f.alternate() {
write!(f, "{}<", last)?;
self.print_type(inner_type, f, use_absolute, cx)?;
write!(f, ">")?;
} else {
write!(f, "{}&lt;", anchor(ty.def_id(), last, cx).to_string())?;
self.print_type(inner_type, f, use_absolute, cx)?;
write!(f, "&gt;")?;
}
} else {
ty.print(cx).fmt(f)?;
}
write!(f, " for ")?; write!(f, " for ")?;
} }
if let clean::Type::Tuple(types) = &self.for_ if let Some(ty) = self.kind.as_blanket_ty() {
&& let [clean::Type::Generic(name)] = &types[..]
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
// Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations`
primitive_link_fragment(
f,
PrimitiveType::Tuple,
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
"#trait-implementations-1",
cx,
)?;
} else if let clean::BareFunction(bare_fn) = &self.for_
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
&bare_fn.decl.inputs.values[..]
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
// Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations`
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
bare_fn.safety.print_with_space().fmt(f)?;
print_abi_with_space(bare_fn.abi).fmt(f)?;
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
primitive_link_fragment(
f,
PrimitiveType::Tuple,
format_args!("fn({name}₁, {name}₂, …, {name}{ellipsis})"),
"#trait-implementations-1",
cx,
)?;
// Write output.
if !bare_fn.decl.output.is_unit() {
write!(f, " -> ")?;
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
}
} else if let Some(ty) = self.kind.as_blanket_ty() {
fmt_type(ty, f, use_absolute, cx)?; fmt_type(ty, f, use_absolute, cx)?;
} else { } else {
fmt_type(&self.for_, f, use_absolute, cx)?; self.print_type(&self.for_, f, use_absolute, cx)?;
} }
print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f) print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f)
}) })
} }
fn print_type<'a, 'tcx: 'a>(
&self,
type_: &clean::Type,
f: &mut fmt::Formatter<'_>,
use_absolute: bool,
cx: &'a Context<'tcx>,
) -> Result<(), fmt::Error> {
if let clean::Type::Tuple(types) = type_
&& let [clean::Type::Generic(name)] = &types[..]
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
// Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations`
primitive_link_fragment(
f,
PrimitiveType::Tuple,
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
"#trait-implementations-1",
cx,
)?;
} else if let clean::Type::Array(ty, len) = type_
&& let clean::Type::Generic(name) = &**ty
&& &len[..] == "1"
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?;
} else if let clean::BareFunction(bare_fn) = &type_
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
&bare_fn.decl.inputs.values[..]
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
// Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations`
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
bare_fn.safety.print_with_space().fmt(f)?;
print_abi_with_space(bare_fn.abi).fmt(f)?;
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
primitive_link_fragment(
f,
PrimitiveType::Tuple,
format_args!("fn({name}₁, {name}₂, …, {name}{ellipsis})"),
"#trait-implementations-1",
cx,
)?;
// Write output.
if !bare_fn.decl.output.is_unit() {
write!(f, " -> ")?;
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
}
} else {
fmt_type(&type_, f, use_absolute, cx)?;
}
Ok(())
}
} }
impl clean::Arguments { impl clean::Arguments {

View File

@ -16,3 +16,20 @@ pub trait Bar {}
//@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)' //@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
#[doc(fake_variadic)] #[doc(fake_variadic)]
impl<U: Foo> Bar for (U,) {} impl<U: Foo> Bar for (U,) {}
pub trait Baz<T> { fn baz(&self) -> T { todo!() } }
//@ has foo/trait.Baz.html
//@ has - '//section[@id="impl-Baz%3C(T,)%3E-for-%5BT;+1%5D"]/h3' 'impl<T> Baz<(T₁, T₂, …, Tₙ)> for [T; N]'
#[doc(fake_variadic)]
impl<T> Baz<(T,)> for [T; 1] {}
//@ has foo/trait.Baz.html
//@ has - '//section[@id="impl-Baz%3C%5BT;+1%5D%3E-for-(T,)"]/h3' 'impl<T> Baz<[T; N]> for (T₁, T₂, …, Tₙ)'
#[doc(fake_variadic)]
impl<T> Baz<[T; 1]> for (T,) {}
//@ has foo/trait.Baz.html
//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)'
#[doc(fake_variadic)]
impl<T> Baz<T> for (T,) {}

View File

@ -0,0 +1,14 @@
//@ check-pass
fn higher_ranked_fndef(ctx: &mut ()) {}
fn test(higher_ranked_fnptr: fn(&mut ())) {
fn as_unsafe<T>(_: unsafe fn(T)) {}
// Make sure that we can cast higher-ranked fn items and pointers to
// a non-higher-ranked target.
as_unsafe(higher_ranked_fndef);
as_unsafe(higher_ranked_fnptr);
}
fn main() {}

View File

@ -1,6 +1,4 @@
//@ run-pass //@ run-pass
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs, staged_api)] #![feature(rustc_attrs, staged_api)]
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]

View File

@ -28,9 +28,11 @@ const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
// conformity is required // conformity is required
const fn bar3() -> u32 { const fn bar3() -> u32 {
let x = std::cell::Cell::new(0u32); let x = std::cell::Cell::new(0u32);
x.get() x.get();
//~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]` //~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]`
//~| ERROR cannot call non-const fn //~| ERROR cannot call non-const fn
foo()
//~^ ERROR is not yet stable as a const fn
} }
// check whether this function cannot be called even with the feature gate active // check whether this function cannot be called even with the feature gate active

View File

@ -17,7 +17,7 @@ LL | const fn bar2() -> u32 { foo2() }
error: const-stable function cannot use `#[feature(const_refs_to_cell)]` error: const-stable function cannot use `#[feature(const_refs_to_cell)]`
--> $DIR/min_const_fn_libstd_stability.rs:31:5 --> $DIR/min_const_fn_libstd_stability.rs:31:5
| |
LL | x.get() LL | x.get();
| ^ | ^
| |
help: if it is not part of the public API, make this function unstably const help: if it is not part of the public API, make this function unstably const
@ -25,7 +25,7 @@ help: if it is not part of the public API, make this function unstably const
LL + #[rustc_const_unstable(feature = "...", issue = "...")] LL + #[rustc_const_unstable(feature = "...", issue = "...")]
LL | const fn bar3() -> u32 { LL | const fn bar3() -> u32 {
| |
help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
| |
LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)]
LL | const fn bar3() -> u32 { LL | const fn bar3() -> u32 {
@ -34,19 +34,27 @@ LL | const fn bar3() -> u32 {
error[E0015]: cannot call non-const fn `Cell::<u32>::get` in constant functions error[E0015]: cannot call non-const fn `Cell::<u32>::get` in constant functions
--> $DIR/min_const_fn_libstd_stability.rs:31:7 --> $DIR/min_const_fn_libstd_stability.rs:31:7
| |
LL | x.get() LL | x.get();
| ^^^^^ | ^^^^^
| |
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: `foo` is not yet stable as a const fn
--> $DIR/min_const_fn_libstd_stability.rs:34:5
|
LL | foo()
| ^^^^^
|
= help: const-stable functions can only call other const-stable functions
error: `foo2_gated` is not yet stable as a const fn error: `foo2_gated` is not yet stable as a const fn
--> $DIR/min_const_fn_libstd_stability.rs:43:32 --> $DIR/min_const_fn_libstd_stability.rs:45:32
| |
LL | const fn bar2_gated() -> u32 { foo2_gated() } LL | const fn bar2_gated() -> u32 { foo2_gated() }
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
| |
= help: const-stable functions can only call other const-stable functions = help: const-stable functions can only call other const-stable functions
error: aborting due to 5 previous errors error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0015`. For more information about this error, try `rustc --explain E0015`.

View File

@ -0,0 +1,14 @@
//@ edition: 2021
trait Trait {}
impl dyn Trait {
const CONST: () = ();
}
fn main() {
match () {
Trait::CONST => {}
//~^ ERROR trait objects must include the `dyn` keyword
}
}

View File

@ -0,0 +1,14 @@
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9
|
LL | Trait::CONST => {}
| ^^^^^
|
help: add `dyn` keyword before this trait
|
LL | <dyn Trait>::CONST => {}
| ++++ +
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0782`.

View File

@ -9,7 +9,6 @@ use std::io::prelude::*;
fn test1() -> Result<(), Box<dyn std::error::Error>> { fn test1() -> Result<(), Box<dyn std::error::Error>> {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a function //~^ ERROR the `?` operator can only be used in a function
Ok(()) Ok(())
} }
@ -17,7 +16,6 @@ fn test2() -> Result<(), Box<dyn std::error::Error>> {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a function //~^ ERROR the `?` operator can only be used in a function
println!(); println!();
Ok(()) Ok(())
} }
@ -27,9 +25,8 @@ macro_rules! mac {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a function //~^ ERROR the `?` operator can only be used in a function
println!(); println!();
Ok(())
Ok(()) }
}
}; };
} }
@ -39,23 +36,20 @@ impl A {
fn test4(&self) -> Result<(), Box<dyn std::error::Error>> { fn test4(&self) -> Result<(), Box<dyn std::error::Error>> {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a method //~^ ERROR the `?` operator can only be used in a method
Ok(())
Ok(()) }
}
fn test5(&self) -> Result<(), Box<dyn std::error::Error>> { fn test5(&self) -> Result<(), Box<dyn std::error::Error>> {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a method //~^ ERROR the `?` operator can only be used in a method
println!(); println!();
Ok(())
Ok(()) }
}
} }
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut _file = File::create("foo.txt")?; let mut _file = File::create("foo.txt")?;
//~^ ERROR the `?` operator can only be used in a function //~^ ERROR the `?` operator can only be used in a function
mac!(); mac!();
Ok(()) Ok(())
} }

View File

@ -12,9 +12,7 @@ help: consider adding return type
LL ~ fn test1() -> Result<(), Box<dyn std::error::Error>> { LL ~ fn test1() -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL +
LL + Ok(()) LL + Ok(())
LL + }
| |
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
@ -32,9 +30,7 @@ LL ~ fn test2() -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL | println!(); LL | println!();
LL +
LL + Ok(()) LL + Ok(())
LL + }
| |
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
@ -51,9 +47,8 @@ help: consider adding return type
LL ~ fn test4(&self) -> Result<(), Box<dyn std::error::Error>> { LL ~ fn test4(&self) -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL ~ LL ~ Ok(())
LL + Ok(()) LL ~ }
LL + }
| |
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
@ -71,9 +66,8 @@ LL ~ fn test5(&self) -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL | println!(); LL | println!();
LL ~ LL ~ Ok(())
LL + Ok(()) LL ~ }
LL + }
| |
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
@ -91,9 +85,7 @@ LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL | mac!(); LL | mac!();
LL +
LL + Ok(()) LL + Ok(())
LL + }
| |
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
@ -115,9 +107,8 @@ LL ~ fn test3() -> Result<(), Box<dyn std::error::Error>> {
LL | let mut _file = File::create("foo.txt")?; LL | let mut _file = File::create("foo.txt")?;
LL | LL |
LL | println!(); LL | println!();
LL ~ LL ~ Ok(())
LL + Ok(()) LL ~ }
LL + }
| |
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View File

@ -14,9 +14,7 @@ LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
LL | // error for a `Try` type on a non-`Try` fn LL | // error for a `Try` type on a non-`Try` fn
... ...
LL | try_trait_generic::<()>(); LL | try_trait_generic::<()>();
LL +
LL + Ok(()) LL + Ok(())
LL + }
| |
error[E0277]: the `?` operator can only be applied to values that implement `Try` error[E0277]: the `?` operator can only be applied to values that implement `Try`