diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 942aae3d53600..73d1d891bb989 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -323,9 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), - ExprKind::Err => { - hir::ExprKind::Err(self.dcx().span_delayed_bug(e.span, "lowered ExprKind::Err")) - } + ExprKind::Err => hir::ExprKind::Err(self.dcx().has_errors().unwrap()), ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), ExprKind::Paren(_) | ExprKind::ForLoop { .. } => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 933372fae4eb4..87ed47648c813 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1068,7 +1068,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> { match block { Some(block) => self.lower_block_expr(block), - None => self.expr_err(span, self.dcx().span_delayed_bug(span, "no block")), + None => self.expr_err(span, self.dcx().has_errors().unwrap()), } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 480072ce705aa..6b5fc01424085 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1285,9 +1285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, - TyKind::Err => { - hir::TyKind::Err(self.dcx().span_delayed_bug(t.span, "TyKind::Err lowered")) - } + TyKind::Err => hir::TyKind::Err(self.dcx().has_errors().unwrap()), // Lower the anonymous structs or unions in a nested lowering context. // // ``` diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 5ce6a71c4bdd5..b5c70538c52d3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -117,18 +117,14 @@ struct CfgChecker<'a, 'tcx> { impl<'a, 'tcx> CfgChecker<'a, 'tcx> { #[track_caller] fn fail(&self, location: Location, msg: impl AsRef) { - let span = self.body.source_info(location).span; - // We use `span_delayed_bug` as we might see broken MIR when other errors have already - // occurred. - self.tcx.dcx().span_delayed_bug( - span, - format!( - "broken MIR in {:?} ({}) at {:?}:\n{}", - self.body.source.instance, - self.when, - location, - msg.as_ref() - ), + // We might see broken MIR when other errors have already occurred. + assert!( + self.tcx.dcx().has_errors().is_some(), + "broken MIR in {:?} ({}) at {:?}:\n{}", + self.body.source.instance, + self.when, + location, + msg.as_ref(), ); } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b738ecb54ffc1..d876f28040da1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1315,6 +1315,9 @@ impl DiagCtxtInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } + // Note that because this comes before the `match` below, + // `-Zeagerly-emit-delayed-bugs` continues to work even after we've + // issued an error and stopped recording new delayed bugs. if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs { diagnostic.level = Error; } @@ -1326,18 +1329,20 @@ impl DiagCtxtInner { diagnostic.level = Bug; } DelayedBug => { - // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `delayed_bugs` - // when an error is first emitted, also), but maybe there's a case - // in which that's not sound? otherwise this is really inefficient. - let backtrace = std::backtrace::Backtrace::capture(); - // This `unchecked_error_guaranteed` is valid. It is where the - // `ErrorGuaranteed` for delayed bugs originates. - #[allow(deprecated)] - let guar = ErrorGuaranteed::unchecked_error_guaranteed(); - self.delayed_bugs - .push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar)); - return Some(guar); + // If we have already emitted at least one error, we don't need + // to record the delayed bug, because it'll never be used. + return if let Some(guar) = self.has_errors_or_lint_errors() { + Some(guar) + } else { + let backtrace = std::backtrace::Backtrace::capture(); + // This `unchecked_error_guaranteed` is valid. It is where the + // `ErrorGuaranteed` for delayed bugs originates. + #[allow(deprecated)] + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + self.delayed_bugs + .push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar)); + Some(guar) + }; } Warning if !self.flags.can_emit_warnings => { if diagnostic.has_future_breakage() { @@ -1403,6 +1408,16 @@ impl DiagCtxtInner { } if is_error { + // If we have any delayed bugs recorded, we can discard them + // because they won't be used. (This should only occur if there + // have been no errors previously emitted, because we don't add + // new delayed bugs once the first error is emitted.) + if !self.delayed_bugs.is_empty() { + assert_eq!(self.lint_err_guars.len() + self.err_guars.len(), 0); + self.delayed_bugs.clear(); + self.delayed_bugs.shrink_to_fit(); + } + // This `unchecked_error_guaranteed` is valid. It is where the // `ErrorGuaranteed` for errors and lint errors originates. #[allow(deprecated)] diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index eec86c36aedae..be4b6399e12da 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -34,10 +34,10 @@ pub(super) fn failed_to_match_macro<'cx>( if try_success_result.is_ok() { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - tracker - .cx - .dcx() - .span_delayed_bug(sp, "Macro matching returned a success on the second try"); + assert!( + tracker.cx.dcx().has_errors().is_some(), + "Macro matching returned a success on the second try" + ); } if let Some(result) = tracker.result { diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index a6ac8ecd950ea..cee7c84adb2e9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -243,7 +243,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| { if self_ty.span.can_be_used_for_suggestions() { lint.multipart_suggestion_verbose( - "use `dyn`", + "if this is an object-safe trait, use `dyn`", sugg, Applicability::MachineApplicable, ); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a001044c3e52d..98a27c5ed2093 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -758,8 +758,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // since we should have emitten an error for them earlier, and they will // not be well-formed! if polarity == ty::ImplPolarity::Negative { - self.tcx().dcx().span_delayed_bug( - binding.span, + assert!( + self.tcx().dcx().has_errors().is_some(), "negative trait bounds should not have bindings", ); continue; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7f674a1e7e45f..e7506cee60e7c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1865,13 +1865,13 @@ fn check_variances_for_type_defn<'tcx>( let hir_param = &hir_generics.params[index]; if ty_param.def_id != hir_param.def_id.into() { - // valid programs always have lifetimes before types in the generic parameter list + // Valid programs always have lifetimes before types in the generic parameter list. // ty_generics are normalized to be in this required order, and variances are built // from ty generics, not from hir generics. but we need hir generics to get - // a span out + // a span out. // - // if they aren't in the same order, then the user has written invalid code, and already - // got an error about it (or I'm wrong about this) + // If they aren't in the same order, then the user has written invalid code, and already + // got an error about it (or I'm wrong about this). tcx.dcx().span_delayed_bug( hir_param.span, "hir generics and ty generics in different order", diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 688760a391269..53a5ada410560 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -85,7 +85,7 @@ pub(super) fn check_item( (_, _, Unsafety::Unsafe, Negative) => { // Reported in AST validation - tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "unsafe negative impl"); + assert!(tcx.dcx().has_errors().is_some(), "unsafe negative impl"); Ok(()) } (_, _, Unsafety::Normal, Negative) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index f21de1609cb7f..9a8f287ec14f7 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -139,10 +139,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::Never | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => { - let reported = self + let guar = self .dcx() .span_delayed_bug(span, format!("`{t:?}` should be sized but is not?")); - return Err(reported); + return Err(guar); } }) } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d84bce09ecb1e..b83a0f893f5f8 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -221,8 +221,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if base_ty.is_none() { // When encountering `return [0][0]` outside of a `fn` body we can encounter a base // that isn't in the type table. We assume more relevant errors have already been - // emitted, so we delay an ICE if none have. (#64638) - self.tcx().dcx().span_delayed_bug(e.span, format!("bad base: `{base:?}`")); + // emitted. (#64638) + assert!(self.tcx().dcx().has_errors().is_some(), "bad base: `{base:?}`"); } if let Some(base_ty) = base_ty && let ty::Ref(_, base_ty_inner, _) = *base_ty.kind() diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 6137506d4a994..c39d0425f7e25 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -802,14 +802,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } // Errors in earlier passes can yield error variables without - // resolution errors here; delay ICE in favor of those errors. - self.tcx().dcx().span_delayed_bug( - self.var_infos[node_idx].origin.span(), - format!( - "collect_error_for_expanding_node() could not find \ - error for var {node_idx:?} in universe {node_universe:?}, lower_bounds={lower_bounds:#?}, \ - upper_bounds={upper_bounds:#?}" - ), + // resolution errors here; ICE if no errors have been emitted yet. + assert!( + self.tcx().dcx().has_errors().is_some(), + "collect_error_for_expanding_node() could not find error for var {node_idx:?} in \ + universe {node_universe:?}, lower_bounds={lower_bounds:#?}, \ + upper_bounds={upper_bounds:#?}", ); } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 7208f17fb340f..c0a99e5cc4177 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -300,9 +300,9 @@ where self.components_must_outlive(origin, subcomponents, region, category); } Component::UnresolvedInferenceVariable(v) => { - // ignore this, we presume it will yield an error - // later, since if a type variable is not resolved by - // this point it never will be + // Ignore this, we presume it will yield an error later, + // since if a type variable is not resolved by this point + // it never will be. self.tcx.dcx().span_delayed_bug( origin.span(), format!("unresolved inference variable in outlives: {v:?}"), diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 24b351988bf69..3ef37bf3466f1 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -172,13 +172,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { self.bound_from_components(components, visited) } Component::UnresolvedInferenceVariable(v) => { - // ignore this, we presume it will yield an error - // later, since if a type variable is not resolved by - // this point it never will be + // Ignore this, we presume it will yield an error later, since + // if a type variable is not resolved by this point it never + // will be. self.tcx .dcx() .delayed_bug(format!("unresolved inference variable in outlives: {v:?}")); - // add a bound that never holds + // Add a bound that never holds. VerifyBound::AnyBound(vec![]) } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 5ae080d470235..0862204d88e2d 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -431,14 +431,13 @@ pub fn check_ast_node_inner<'a, T: EarlyLintPass>( // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. for (id, lints) in cx.context.buffered.map { - for early_lint in lints { - sess.dcx().span_delayed_bug( - early_lint.span, - format!( - "failed to process buffered lint here (dummy = {})", - id == ast::DUMMY_NODE_ID - ), + if !lints.is_empty() { + assert!( + sess.dcx().has_errors().is_some(), + "failed to process buffered lint here (dummy = {})", + id == ast::DUMMY_NODE_ID ); + break; } } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 6ffa0819f3571..2a6f473cd32f3 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -207,6 +207,11 @@ pub fn explain_lint_level_source( err: &mut Diagnostic, ) { let name = lint.name_lower(); + if let Level::Allow = level { + // Do not point at `#[allow(compat_lint)]` as the reason for a compatibility lint + // triggering. (#121009) + return; + } match src { LintLevelSource::Default => { err.note_once(format!("`#[{}({})]` on by default", level.as_str(), name)); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 23771073745ff..5e4d899f51768 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -35,6 +35,16 @@ impl<'tcx> IntoKind for Const<'tcx> { } } +impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> { + fn flags(&self) -> TypeFlags { + self.0.flags + } + + fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex { + self.0.outer_exclusive_binder + } +} + impl<'tcx> ConstTy> for Const<'tcx> { fn ty(self) -> Ty<'tcx> { self.ty() @@ -63,11 +73,13 @@ impl<'tcx> Const<'tcx> { self.0.kind } + // FIXME(compiler-errors): Think about removing this. #[inline] pub fn flags(self) -> TypeFlags { self.0.flags } + // FIXME(compiler-errors): Think about removing this. #[inline] pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex { self.0.outer_exclusive_binder diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bd86c1c284e6e..61e449b8b565f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -28,7 +28,7 @@ use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, - Visibility, + TypeVisitable, Visibility, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; @@ -87,7 +87,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; - type Binder = Binder<'tcx, T>; + type Binder>> = Binder<'tcx, T>; + type BoundVars = &'tcx List; + type BoundVar = ty::BoundVariableKind; type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; @@ -151,6 +153,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> Self::Const { Const::new_bound(self, debruijn, var, ty) } + + fn expect_error_or_delayed_bug() { + let has_errors = ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs()); + assert!(has_errors.is_some()); + } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2d6c6cfbcd144..15bddb2a64fb8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -504,6 +504,16 @@ impl<'tcx> IntoKind for Ty<'tcx> { } } +impl<'tcx> rustc_type_ir::visit::Flags for Ty<'tcx> { + fn flags(&self) -> TypeFlags { + self.0.flags + } + + fn outer_exclusive_binder(&self) -> DebruijnIndex { + self.0.outer_exclusive_binder + } +} + impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 200811940ed76..b63f9c6dfa01a 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -29,6 +29,16 @@ pub struct Predicate<'tcx>( pub(super) Interned<'tcx, WithCachedTypeInfo>>>, ); +impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> { + fn flags(&self) -> TypeFlags { + self.0.flags + } + + fn outer_exclusive_binder(&self) -> ty::DebruijnIndex { + self.0.outer_exclusive_binder + } +} + impl<'tcx> Predicate<'tcx> { /// Gets the inner `ty::Binder<'tcx, PredicateKind<'tcx>>`. #[inline] @@ -36,11 +46,13 @@ impl<'tcx> Predicate<'tcx> { self.0.internee } + // FIXME(compiler-errors): Think about removing this. #[inline(always)] pub fn flags(self) -> TypeFlags { self.0.flags } + // FIXME(compiler-errors): Think about removing this. #[inline(always)] pub fn outer_exclusive_binder(self) -> DebruijnIndex { self.0.outer_exclusive_binder diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 1191d7fca32a4..b206727f0514e 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -26,6 +26,19 @@ impl<'tcx> rustc_type_ir::IntoKind for Region<'tcx> { } } +impl<'tcx> rustc_type_ir::visit::Flags for Region<'tcx> { + fn flags(&self) -> TypeFlags { + self.type_flags() + } + + fn outer_exclusive_binder(&self) -> ty::DebruijnIndex { + match **self { + ty::ReBound(debruijn, _) => debruijn.shifted_in(1), + _ => ty::INNERMOST, + } + } +} + impl<'tcx> Region<'tcx> { #[inline] pub fn new_early_param( diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a3d5f1f195510..ae6544b9dbea0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -942,6 +942,16 @@ where } } +impl<'tcx, T> rustc_type_ir::BoundVars> for ty::Binder<'tcx, T> { + fn bound_vars(&self) -> &'tcx List { + self.bound_vars + } + + fn has_no_bound_vars(&self) -> bool { + self.bound_vars.is_empty() + } +} + impl<'tcx, T> Binder<'tcx, T> { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about @@ -1808,6 +1818,7 @@ impl<'tcx> Ty<'tcx> { self.0.0 } + // FIXME(compiler-errors): Think about removing this. #[inline(always)] pub fn flags(self) -> TypeFlags { self.0.0.flags diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c674a868d9fa2..09bb06de483a8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1320,6 +1320,7 @@ impl<'tcx> Ty<'tcx> { ty } + // FIXME(compiler-errors): Think about removing this. #[inline] pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex { self.0.outer_exclusive_binder diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 7acdb931f1ae7..59292a281edec 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -1,140 +1,10 @@ use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_errors::ErrorGuaranteed; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; use std::ops::ControlFlow; -pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; - -pub trait TypeVisitableExt<'tcx>: TypeVisitable> { - /// Returns `true` if `self` has any late-bound regions that are either - /// bound by `binder` or bound by some binder outside of `binder`. - /// If `binder` is `ty::INNERMOST`, this indicates whether - /// there are any late-bound regions that appear free. - fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() - } - - /// Returns `true` if this type has any regions that escape `binder` (and - /// hence are not bound by it). - fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { - self.has_vars_bound_at_or_above(binder.shifted_in(1)) - } - - /// Return `true` if this type has regions that are not a part of the type. - /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` - /// would return `true`. The latter can occur when traversing through the - /// former. - /// - /// See [`HasEscapingVarsVisitor`] for more information. - fn has_escaping_bound_vars(&self) -> bool { - self.has_vars_bound_at_or_above(ty::INNERMOST) - } - - fn has_type_flags(&self, flags: TypeFlags) -> bool { - let res = - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags); - trace!(?self, ?flags, ?res, "has_type_flags"); - res - } - fn has_projections(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PROJECTION) - } - fn has_inherent_projections(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_INHERENT) - } - fn has_opaque_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) - } - fn has_coroutines(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_COROUTINE) - } - fn references_error(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_ERROR) - } - fn error_reported(&self) -> Result<(), ErrorGuaranteed> { - if self.references_error() { - // We must include lint errors and delayed bugs here. - if let Some(reported) = - ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs()) - { - Err(reported) - } else { - bug!("expected some kind of error in `error_reported`"); - } - } else { - Ok(()) - } - } - fn has_non_region_param(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) - } - fn has_infer_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_INFER) - } - fn has_infer_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_INFER) - } - fn has_non_region_infer(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER) - } - fn has_infer(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_INFER) - } - fn has_placeholders(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PLACEHOLDER) - } - fn has_non_region_placeholders(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER) - } - fn has_param(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PARAM) - } - /// "Free" regions in this context means that it has any region - /// that is not (a) erased or (b) late-bound. - fn has_free_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) - } - - fn has_erased_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_ERASED) - } - - /// True if there are any un-erased free regions. - fn has_erasable_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) - } - - /// Indicates whether this value references only 'global' - /// generic parameters that are the same regardless of what fn we are - /// in. This is used for caching. - fn is_global(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) - } - - /// True if there are any late-bound regions - fn has_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_BOUND) - } - /// True if there are any late-bound non-region variables - fn has_non_region_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) - } - /// True if there are any bound variables - fn has_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_BOUND_VARS) - } - - /// Indicates whether this value still has parameters/placeholders/inference variables - /// which could be replaced later, in a way that would change the results of `impl` - /// specialization. - fn still_further_specializable(&self) -> bool { - self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) - } -} - -impl<'tcx, T: TypeVisitable>> TypeVisitableExt<'tcx> for T {} +pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; /////////////////////////////////////////////////////////////////////////// // Region folder @@ -370,185 +240,6 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { } } -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -struct FoundEscapingVars; - -/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a -/// bound region or a bound type. -/// -/// So, for example, consider a type like the following, which has two binders: -/// -/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope -/// -/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the -/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner -/// fn type*, that type has an escaping region: `'a`. -/// -/// Note that what I'm calling an "escaping var" is often just called a "free var". However, -/// we already use the term "free var". It refers to the regions or types that we use to represent -/// bound regions or type params on a fn definition while we are type checking its body. -/// -/// To clarify, conceptually there is no particular difference between -/// an "escaping" var and a "free" var. However, there is a big -/// difference in practice. Basically, when "entering" a binding -/// level, one is generally required to do some sort of processing to -/// a bound var, such as replacing it with a fresh/placeholder -/// var, or making an entry in the environment to represent the -/// scope to which it is attached, etc. An escaping var represents -/// a bound var for which this processing has not yet been done. -struct HasEscapingVarsVisitor { - /// Anything bound by `outer_index` or "above" is escaping. - outer_index: ty::DebruijnIndex, -} - -impl<'tcx> TypeVisitor> for HasEscapingVarsVisitor { - type BreakTy = FoundEscapingVars; - - fn visit_binder>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - self.outer_index.shift_in(1); - let result = t.super_visit_with(self); - self.outer_index.shift_out(1); - result - } - - #[inline] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - // If the outer-exclusive-binder is *strictly greater* than - // `outer_index`, that means that `t` contains some content - // bound at `outer_index` or above (because - // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping vars. - if t.outer_exclusive_binder() > self.outer_index { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::Continue(()) - } - } - - #[inline] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - // If the region is bound by `outer_index` or anything outside - // of outer index, then it escapes the binders we have - // visited. - if r.bound_at_or_above_binder(self.outer_index) { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::Continue(()) - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { - // If the outer-exclusive-binder is *strictly greater* than - // `outer_index`, that means that `ct` contains some content - // bound at `outer_index` or above (because - // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping vars. - if ct.outer_exclusive_binder() > self.outer_index { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::Continue(()) - } - } - - #[inline] - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { - if predicate.outer_exclusive_binder() > self.outer_index { - ControlFlow::Break(FoundEscapingVars) - } else { - ControlFlow::Continue(()) - } - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -struct FoundFlags; - -// FIXME: Optimize for checking for infer flags -struct HasTypeFlagsVisitor { - flags: ty::TypeFlags, -} - -impl std::fmt::Debug for HasTypeFlagsVisitor { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.flags.fmt(fmt) - } -} - -// Note: this visitor traverses values down to the level of -// `Ty`/`Const`/`Predicate`, but not within those types. This is because the -// type flags at the outer layer are enough. So it's faster than it first -// looks, particular for `Ty`/`Predicate` where it's just a field access. -// -// N.B. The only case where this isn't totally true is binders, which also -// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that -// are present, regardless of whether those bound variables are used. This -// is important for anonymization of binders in `TyCtxt::erase_regions`. We -// specifically detect this case in `visit_binder`. -impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { - type BreakTy = FoundFlags; - - fn visit_binder>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - // If we're looking for the HAS_BINDER_VARS flag, check if the - // binder has vars. This won't be present in the binder's bound - // value, so we need to check here too. - if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { - return ControlFlow::Break(FoundFlags); - } - - t.super_visit_with(self) - } - - #[inline] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - // Note: no `super_visit_with` call. - let flags = t.flags(); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::Continue(()) - } - } - - #[inline] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - // Note: no `super_visit_with` call, as usual for `Region`. - let flags = r.type_flags(); - if flags.intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::Continue(()) - } - } - - #[inline] - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { - // Note: no `super_visit_with` call. - if c.flags().intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::Continue(()) - } - } - - #[inline] - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { - // Note: no `super_visit_with` call. - if predicate.flags().intersects(self.flags) { - ControlFlow::Break(FoundFlags) - } else { - ControlFlow::Continue(()) - } - } -} - /// Collects all the late-bound regions at the innermost binding level /// into a hash set. struct LateBoundRegionsCollector { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 8688c58906331..241b6c6cb2cad 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -33,7 +33,7 @@ struct UnsafetyVisitor<'a, 'tcx> { body_target_features: &'tcx [Symbol], /// When inside the LHS of an assignment to a field, this is the type /// of the LHS and the span of the assignment expression. - assignment_info: Option<(Ty<'tcx>, Span)>, + assignment_info: Option>, in_union_destructure: bool, param_env: ParamEnv<'tcx>, inside_adt: bool, @@ -473,10 +473,15 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() { - if let Some((assigned_ty, assignment_span)) = self.assignment_info { + if let Some(assigned_ty) = self.assignment_info { if assigned_ty.needs_drop(self.tcx, self.param_env) { - // This would be unsafe, but should be outright impossible since we reject such unions. - self.tcx.dcx().span_delayed_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}")); + // This would be unsafe, but should be outright impossible since we + // reject such unions. + assert!( + self.tcx.dcx().has_errors().is_some(), + "union fields that need dropping should be impossible: \ + {assigned_ty}" + ); } } else { self.requires_unsafe(expr.span, AccessToUnionField); @@ -492,14 +497,15 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); } - // Second, check for accesses to union fields - // don't have any special handling for AssignOp since it causes a read *and* write to lhs + // Second, check for accesses to union fields. Don't have any + // special handling for AssignOp since it causes a read *and* + // write to lhs. if matches!(expr.kind, ExprKind::Assign { .. }) { - self.assignment_info = Some((lhs.ty, expr.span)); + self.assignment_info = Some(lhs.ty); visit::walk_expr(self, lhs); self.assignment_info = None; visit::walk_expr(self, &self.thir()[rhs]); - return; // we have already visited everything by now + return; // We have already visited everything by now. } } ExprKind::Borrow { borrow_kind, arg } => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 18a00724c3d0e..c77c80d9f4b29 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -153,8 +153,7 @@ impl<'tcx> ConstToPat<'tcx> { // a hard error when we don't have a valtree or when we find something in // the valtree that is not structural; then this can all be made a lot simpler. - let structural = - traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); + let structural = traits::search_for_structural_match_violation(self.tcx(), cv.ty()); debug!( "search_for_structural_match_violation cv.ty: {:?} returned: {:?}", cv.ty(), diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index fbb626953835e..a0c3de3af5862 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -243,10 +243,11 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { // old value is being dropped. let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty; if assigned_ty.needs_drop(self.tcx, self.param_env) { - // This would be unsafe, but should be outright impossible since we reject such unions. - self.tcx.dcx().span_delayed_bug( - self.source_info.span, - format!("union fields that need dropping should be impossible: {assigned_ty}") + // This would be unsafe, but should be outright impossible since we reject + // such unions. + assert!( + self.tcx.dcx().has_errors().is_some(), + "union fields that need dropping should be impossible: {assigned_ty}" ); } } else { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8d4afd5b5dce5..370f0db72cb78 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -561,9 +561,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .ok()?; dest.into() } - CastKind::FnPtrToPtr - | CastKind::PtrToPtr - | CastKind::PointerCoercion( + CastKind::FnPtrToPtr | CastKind::PtrToPtr => { + let src = self.evaluated[value].as_ref()?; + let src = self.ecx.read_immediate(src).ok()?; + let to = self.ecx.layout_of(to).ok()?; + let ret = self.ecx.ptr_to_ptr(&src, to).ok()?; + ret.into() + } + CastKind::PointerCoercion( ty::adjustment::PointerCoercion::MutToConstPointer | ty::adjustment::PointerCoercion::ArrayToPointer | ty::adjustment::PointerCoercion::UnsafeFnPointer, @@ -571,8 +576,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let src = self.evaluated[value].as_ref()?; let src = self.ecx.read_immediate(src).ok()?; let to = self.ecx.layout_of(to).ok()?; - let ret = self.ecx.ptr_to_ptr(&src, to).ok()?; - ret.into() + ImmTy::from_immediate(*src, to).into() } _ => return None, }, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9f30f2836f195..c11fd5fcc90c5 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -265,7 +265,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { let body = &tcx.mir_const(def).borrow(); if body.return_ty().references_error() { - tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors"); + assert!(tcx.dcx().has_errors().is_some(), "mir_const_qualif: MIR had errors"); return Default::default(); } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 42edbeaa622c2..cd434fecce2cb 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy, InferCtxtLike, Interner, IntoKind, PlaceholderLike, @@ -62,8 +63,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc let value = value.fold_with(&mut canonicalizer); // FIXME: Restore these assertions. Should we uplift type flags? - // assert!(!value.has_infer(), "unexpected infer in {value:?}"); - // assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); + assert!(!value.has_infer(), "unexpected infer in {value:?}"); + assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); let (max_universe, variables) = canonicalizer.finalize(); diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 9158ba00901c6..754757b5de539 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -429,16 +429,16 @@ where let formatter = query.format_value(); if old_hash != new_hash { // We have an inconsistency. This can happen if one of the two - // results is tainted by errors. In this case, delay a bug to - // ensure compilation is doomed. - qcx.dep_context().sess().dcx().delayed_bug(format!( + // results is tainted by errors. + assert!( + qcx.dep_context().sess().dcx().has_errors().is_some(), "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\ computed={:#?}\nfed={:#?}", query.dep_kind(), key, formatter(&result), formatter(&cached_result), - )); + ); } } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 522c645253a21..1edf6b11fc343 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -62,9 +62,10 @@ pub fn is_const_evaluatable<'tcx>( match unexpanded_ct.kind() { ty::ConstKind::Expr(_) => { - // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but - // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it - // is evaluatable or not. For now we just ICE until this is implemented. + // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, + // but currently it is not possible to evaluate `ConstKind::Expr` so we are unable + // to tell if it is evaluatable or not. For now we just ICE until this is + // implemented. Err(NotConstEvaluatable::Error(tcx.dcx().span_delayed_bug( span, "evaluating `ConstKind::Expr` is not currently supported", diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c7b56aac7e55b..335e6ff28226e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3041,7 +3041,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { this = "the implicit `Sized` requirement on this type parameter"; } if let Some(hir::Node::TraitItem(hir::TraitItem { - ident, + generics, kind: hir::TraitItemKind::Type(bounds, None), .. })) = tcx.hir().get_if_local(item_def_id) @@ -3053,7 +3053,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let (span, separator) = if let [.., last] = bounds { (last.span().shrink_to_hi(), " +") } else { - (ident.span.shrink_to_hi(), ":") + (generics.span.shrink_to_hi(), ":") }; err.span_suggestion_verbose( span, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index c5ee03916825c..2c8d3fc9de241 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -236,9 +236,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - // It could be that we don't report an error because we have seen an `ErrorReported` from another source. - // We should probably be able to fix most of these, but some are delayed bugs that get a proper error - // after this function. + // It could be that we don't report an error because we have seen an `ErrorReported` from + // another source. We should probably be able to fix most of these, but some are delayed + // bugs that get a proper error after this function. reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors")) } @@ -519,7 +519,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref, span, ) { - GetSafeTransmuteErrorAndReason::Silent => return self.dcx().span_delayed_bug(span, "silent safe transmute error"), + GetSafeTransmuteErrorAndReason::Silent => { + return self.dcx().span_delayed_bug( + span, "silent safe transmute error" + ); + } GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation, @@ -2990,7 +2994,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { (s, " +") } else { - (span.shrink_to_hi(), ":") + (param.name.ident().span.shrink_to_hi(), ":") }; err.span_suggestion_verbose( span, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 29a4a078fe03f..7b715984c2b27 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -555,7 +555,7 @@ fn virtual_call_violations_for_method<'tcx>( // NOTE: This check happens last, because it results in a lint, and not a // hard error. - if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| { + if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| { // dyn Trait is okay: // // trait Trait { @@ -594,7 +594,10 @@ fn virtual_call_violations_for_method<'tcx>( // would already have reported an error at the definition of the // auto trait. if pred_trait_ref.args.len() != 1 { - tcx.dcx().span_delayed_bug(span, "auto traits cannot have generic parameters"); + assert!( + tcx.dcx().has_errors().is_some(), + "auto traits cannot have generic parameters" + ); } return false; } diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 89459f377dd2b..e6b42f15d5140 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use rustc_span::Span; use std::ops::ControlFlow; /// This method traverses the structure of `ty`, trying to find an @@ -30,19 +29,16 @@ use std::ops::ControlFlow; /// that arose when the requirement was not enforced completely, see /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. pub fn search_for_structural_match_violation<'tcx>( - span: Span, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> Option> { - ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value() + ty.visit_with(&mut Search { tcx, seen: FxHashSet::default() }).break_value() } /// This implements the traversal over the structure of a given type to try to /// find instances of ADTs (specifically structs or enums) that do not implement /// `StructuralPartialEq`. struct Search<'tcx> { - span: Span, - tcx: TyCtxt<'tcx>, /// Tracks ADTs previously encountered during search, so that @@ -138,7 +134,6 @@ impl<'tcx> TypeVisitor> for Search<'tcx> { bug!("unexpected type during structural-match checking: {:?}", ty); } ty::Error(_) => { - self.tcx.dcx().span_delayed_bug(self.span, "ty::Error in structural-match check"); // We still want to check other types after encountering an error, // as this may still emit relevant errors. return ControlFlow::Continue(()); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs new file mode 100644 index 0000000000000..57f961ac97ec5 --- /dev/null +++ b/compiler/rustc_type_ir/src/binder.rs @@ -0,0 +1,7 @@ +use crate::Interner; + +pub trait BoundVars { + fn bound_vars(&self) -> I::BoundVars; + + fn has_no_bound_vars(&self) -> bool; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 188910ecc52d1..7728ee0e842a8 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -2,9 +2,10 @@ use smallvec::SmallVec; use std::fmt::Debug; use std::hash::Hash; +use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ - BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, RegionKind, TyKind, - UniverseIndex, + BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, RegionKind, + TyKind, UniverseIndex, }; pub trait Interner: Sized { @@ -19,7 +20,10 @@ pub trait Interner: Sized { type GenericArg: Copy + DebugWithInfcx + Hash + Ord; type Term: Copy + Debug + Hash + Ord; - type Binder; + type Binder>: BoundVars + TypeSuperVisitable; + type BoundVars: IntoIterator; + type BoundVar; + type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; // Kinds of tys @@ -28,7 +32,9 @@ pub trait Interner: Sized { + Hash + Ord + Into - + IntoKind>; + + IntoKind> + + TypeSuperVisitable + + Flags; type Tys: Copy + Debug + Hash + Ord + IntoIterator; type AliasTy: Copy + DebugWithInfcx + Hash + Ord; type ParamTy: Copy + Debug + Hash + Ord; @@ -48,7 +54,9 @@ pub trait Interner: Sized { + Ord + Into + IntoKind> - + ConstTy; + + ConstTy + + TypeSuperVisitable + + Flags; type AliasConst: Copy + DebugWithInfcx + Hash + Ord; type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike; type ParamConst: Copy + Debug + Hash + Ord; @@ -62,7 +70,8 @@ pub trait Interner: Sized { + Hash + Ord + Into - + IntoKind>; + + IntoKind> + + Flags; type EarlyParamRegion: Copy + Debug + Hash + Ord; type LateParamRegion: Copy + Debug + Hash + Ord; type BoundRegion: Copy + Debug + Hash + Ord; @@ -70,7 +79,7 @@ pub trait Interner: Sized { type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike; // Predicates - type Predicate: Copy + Debug + Hash + Eq; + type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; type TraitPredicate: Copy + Debug + Hash + Eq; type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; @@ -86,6 +95,9 @@ pub trait Interner: Sized { fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty; fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region; fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const; + + /// Assert that an error has been delayed or emitted. + fn expect_error_or_delayed_bug(); } /// Common capabilities of placeholder kinds diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index f498c5531fcff..94ccbcbd8a570 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -30,6 +30,7 @@ pub mod visit; #[macro_use] mod macros; +mod binder; mod canonical; mod const_kind; mod debug; @@ -39,6 +40,7 @@ mod interner; mod predicate_kind; mod region_kind; +pub use binder::*; pub use canonical::*; #[cfg(feature = "nightly")] pub use codec::*; diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 7aa990046675f..638fb9f7fa9db 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -45,8 +45,7 @@ use rustc_index::{Idx, IndexVec}; use std::fmt; use std::ops::ControlFlow; -use crate::Interner; -use crate::Lrc; +use crate::{self as ty, BoundVars, Interner, IntoKind, Lrc, TypeFlags}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -88,38 +87,28 @@ pub trait TypeVisitor: Sized { #[cfg(not(feature = "nightly"))] type BreakTy; - fn visit_binder>(&mut self, t: &I::Binder) -> ControlFlow - where - I::Binder: TypeSuperVisitable, - { + fn visit_binder>( + &mut self, + t: &I::Binder, + ) -> ControlFlow { t.super_visit_with(self) } - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow - where - I::Ty: TypeSuperVisitable, - { + fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { t.super_visit_with(self) } // The default region visitor is a no-op because `Region` is non-recursive - // and has no `super_visit_with` method to call. That also explains the - // lack of `I::Region: TypeSuperVisitable` bound. + // and has no `super_visit_with` method to call. fn visit_region(&mut self, _r: I::Region) -> ControlFlow { ControlFlow::Continue(()) } - fn visit_const(&mut self, c: I::Const) -> ControlFlow - where - I::Const: TypeSuperVisitable, - { + fn visit_const(&mut self, c: I::Const) -> ControlFlow { c.super_visit_with(self) } - fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow - where - I::Predicate: TypeSuperVisitable, - { + fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow { p.super_visit_with(self) } } @@ -200,3 +189,363 @@ impl, Ix: Idx> TypeVisitable for IndexVec TypeFlags; + fn outer_exclusive_binder(&self) -> ty::DebruijnIndex; +} + +pub trait TypeVisitableExt: TypeVisitable { + fn has_type_flags(&self, flags: TypeFlags) -> bool; + + /// Returns `true` if `self` has any late-bound regions that are either + /// bound by `binder` or bound by some binder outside of `binder`. + /// If `binder` is `ty::INNERMOST`, this indicates whether + /// there are any late-bound regions that appear free. + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool; + + /// Returns `true` if this type has any regions that escape `binder` (and + /// hence are not bound by it). + fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { + self.has_vars_bound_at_or_above(binder.shifted_in(1)) + } + + /// Return `true` if this type has regions that are not a part of the type. + /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` + /// would return `true`. The latter can occur when traversing through the + /// former. + /// + /// See [`HasEscapingVarsVisitor`] for more information. + fn has_escaping_bound_vars(&self) -> bool { + self.has_vars_bound_at_or_above(ty::INNERMOST) + } + + fn has_projections(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PROJECTION) + } + + fn has_inherent_projections(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INHERENT) + } + + fn has_opaque_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) + } + + fn has_coroutines(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_COROUTINE) + } + + fn references_error(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_ERROR) + } + + fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>; + + fn has_non_region_param(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) + } + + fn has_infer_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_INFER) + } + + fn has_infer_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INFER) + } + + fn has_non_region_infer(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER) + } + + fn has_infer(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_INFER) + } + + fn has_placeholders(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PLACEHOLDER) + } + + fn has_non_region_placeholders(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER) + } + + fn has_param(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PARAM) + } + + /// "Free" regions in this context means that it has any region + /// that is not (a) erased or (b) late-bound. + fn has_free_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + fn has_erased_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_ERASED) + } + + /// True if there are any un-erased free regions. + fn has_erasable_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + /// Indicates whether this value references only 'global' + /// generic parameters that are the same regardless of what fn we are + /// in. This is used for caching. + fn is_global(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) + } + + /// True if there are any late-bound regions + fn has_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_BOUND) + } + /// True if there are any late-bound non-region variables + fn has_non_region_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) + } + /// True if there are any bound variables + fn has_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS) + } + + /// Indicates whether this value still has parameters/placeholders/inference variables + /// which could be replaced later, in a way that would change the results of `impl` + /// specialization. + fn still_further_specializable(&self) -> bool { + self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) + } +} + +impl> TypeVisitableExt for T { + fn has_type_flags(&self, flags: TypeFlags) -> bool { + let res = + self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags); + res + } + + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() + } + + fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> { + if self.references_error() { + if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) { + Err(guar) + } else { + panic!("type flags said there was an error, but now there is not") + } + } else { + Ok(()) + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundFlags; + +// FIXME: Optimize for checking for infer flags +struct HasTypeFlagsVisitor { + flags: ty::TypeFlags, +} + +impl std::fmt::Debug for HasTypeFlagsVisitor { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.flags.fmt(fmt) + } +} + +// Note: this visitor traverses values down to the level of +// `Ty`/`Const`/`Predicate`, but not within those types. This is because the +// type flags at the outer layer are enough. So it's faster than it first +// looks, particular for `Ty`/`Predicate` where it's just a field access. +// +// N.B. The only case where this isn't totally true is binders, which also +// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that +// are present, regardless of whether those bound variables are used. This +// is important for anonymization of binders in `TyCtxt::erase_regions`. We +// specifically detect this case in `visit_binder`. +impl TypeVisitor for HasTypeFlagsVisitor { + type BreakTy = FoundFlags; + + fn visit_binder>( + &mut self, + t: &I::Binder, + ) -> ControlFlow { + // If we're looking for the HAS_BINDER_VARS flag, check if the + // binder has vars. This won't be present in the binder's bound + // value, so we need to check here too. + if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.has_no_bound_vars() { + return ControlFlow::Break(FoundFlags); + } + + t.super_visit_with(self) + } + + #[inline] + fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + // Note: no `super_visit_with` call. + let flags = t.flags(); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_region(&mut self, r: I::Region) -> ControlFlow { + // Note: no `super_visit_with` call, as usual for `Region`. + let flags = r.flags(); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_const(&mut self, c: I::Const) -> ControlFlow { + // Note: no `super_visit_with` call. + if c.flags().intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + // Note: no `super_visit_with` call. + if predicate.flags().intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundEscapingVars; + +/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a +/// bound region or a bound type. +/// +/// So, for example, consider a type like the following, which has two binders: +/// +/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope +/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope +/// +/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the +/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner +/// fn type*, that type has an escaping region: `'a`. +/// +/// Note that what I'm calling an "escaping var" is often just called a "free var". However, +/// we already use the term "free var". It refers to the regions or types that we use to represent +/// bound regions or type params on a fn definition while we are type checking its body. +/// +/// To clarify, conceptually there is no particular difference between +/// an "escaping" var and a "free" var. However, there is a big +/// difference in practice. Basically, when "entering" a binding +/// level, one is generally required to do some sort of processing to +/// a bound var, such as replacing it with a fresh/placeholder +/// var, or making an entry in the environment to represent the +/// scope to which it is attached, etc. An escaping var represents +/// a bound var for which this processing has not yet been done. +struct HasEscapingVarsVisitor { + /// Anything bound by `outer_index` or "above" is escaping. + outer_index: ty::DebruijnIndex, +} + +impl TypeVisitor for HasEscapingVarsVisitor { + type BreakTy = FoundEscapingVars; + + fn visit_binder>( + &mut self, + t: &I::Binder, + ) -> ControlFlow { + self.outer_index.shift_in(1); + let result = t.super_visit_with(self); + self.outer_index.shift_out(1); + result + } + + #[inline] + fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + // If the outer-exclusive-binder is *strictly greater* than + // `outer_index`, that means that `t` contains some content + // bound at `outer_index` or above (because + // `outer_exclusive_binder` is always 1 higher than the + // content in `t`). Therefore, `t` has some escaping vars. + if t.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_region(&mut self, r: I::Region) -> ControlFlow { + // If the region is bound by `outer_index` or anything outside + // of outer index, then it escapes the binders we have + // visited. + if r.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) + } + } + + fn visit_const(&mut self, ct: I::Const) -> ControlFlow { + // If the outer-exclusive-binder is *strictly greater* than + // `outer_index`, that means that `ct` contains some content + // bound at `outer_index` or above (because + // `outer_exclusive_binder` is always 1 higher than the + // content in `t`). Therefore, `t` has some escaping vars. + if ct.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + if predicate.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) + } + } +} + +struct HasErrorVisitor; + +impl TypeVisitor for HasErrorVisitor { + type BreakTy = I::ErrorGuaranteed; + + fn visit_ty(&mut self, t: ::Ty) -> ControlFlow { + if let ty::Error(guar) = t.kind() { + ControlFlow::Break(guar) + } else { + t.super_visit_with(self) + } + } + + fn visit_const(&mut self, c: ::Const) -> ControlFlow { + if let ty::ConstKind::Error(guar) = c.kind() { + ControlFlow::Break(guar) + } else { + c.super_visit_with(self) + } + } + + fn visit_region(&mut self, r: ::Region) -> ControlFlow { + if let ty::ReError(guar) = r.kind() { + ControlFlow::Break(guar) + } else { + ControlFlow::Continue(()) + } + } +} diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 87db8629ad09a..b214f4946b1b5 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -19,7 +19,7 @@ use core::task::Waker; /// The implementation of waking a task on an executor. /// /// This trait can be used to create a [`Waker`]. An executor can define an -/// implementation of this trait, and use that to construct a Waker to pass +/// implementation of this trait, and use that to construct a [`Waker`] to pass /// to the tasks that are executed on that executor. /// /// This trait is a memory-safe and ergonomic alternative to constructing a @@ -28,7 +28,14 @@ use core::task::Waker; /// those for embedded systems) cannot use this API, which is why [`RawWaker`] /// exists as an alternative for those systems. /// -/// [arc]: ../../std/sync/struct.Arc.html +/// To construct a [`Waker`] from some type `W` implementing this trait, +/// wrap it in an [`Arc`](Arc) and call `Waker::from()` on that. +/// It is also possible to convert to [`RawWaker`] in the same way. +/// +/// /// /// # Examples /// @@ -100,7 +107,7 @@ pub trait Wake { #[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for Waker { - /// Use a `Wake`-able type as a `Waker`. + /// Use a [`Wake`]-able type as a `Waker`. /// /// No heap allocations or atomic operations are used for this conversion. fn from(waker: Arc) -> Waker { diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 78091c0172955..1c8e667654469 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -95,8 +95,10 @@ impl fmt::Display for AllocError { /// # Safety /// /// * Memory blocks returned from an allocator that are [*currently allocated*] must point to -/// valid memory and retain their validity while they are [*currently allocated*] and at -/// least one of the instance and all of its clones has not been dropped. +/// valid memory and retain their validity while they are [*currently allocated*] and the shorter +/// of: +/// - the borrow-checker lifetime of the allocator type itself. +/// - as long as at least one of the instance and all of its clones has not been dropped. /// /// * copying, cloning, or moving the allocator must not invalidate memory blocks returned from this /// allocator. A copied or cloned allocator must behave like the same allocator, and @@ -114,6 +116,10 @@ pub unsafe trait Allocator { /// The returned block may have a larger size than specified by `layout.size()`, and may or may /// not have its contents initialized. /// + /// The returned block of memory remains valid as long as it is [*currently allocated*] and the shorter of: + /// - the borrow-checker lifetime of the allocator type itself. + /// - as long as at the allocator and all its clones has not been dropped. + /// /// # Errors /// /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 5f758af162477..34a05ac38884d 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -58,7 +58,7 @@ use crate::mem::transmute; #[unstable(feature = "ascii_char", issue = "110998")] #[repr(u8)] pub enum AsciiChar { - /// U+0000 + /// U+0000 (The default variant) #[unstable(feature = "ascii_char_variants", issue = "110998")] Null = 0, /// U+0001 diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 16618b38769d2..a1303fcd82158 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -2,6 +2,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::ascii::Char as AsciiChar; + /// A trait for giving a type a useful default value. /// /// Sometimes, you want to fall back to some kind of default value, and @@ -158,6 +160,7 @@ macro_rules! default_impl { default_impl! { (), (), "Returns the default value of `()`" } default_impl! { bool, false, "Returns the default value of `false`" } default_impl! { char, '\x00', "Returns the default value of `\\x00`" } +default_impl! { AsciiChar, AsciiChar::Null, "Returns the default value of `Null`" } default_impl! { usize, 0, "Returns the default value of `0`" } default_impl! { u8, 0, "Returns the default value of `0`" } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 09f3f2f02eab1..b9895f7edeaa4 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -9,10 +9,14 @@ use crate::ptr; /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] /// or a [`LocalWaker`] which provides customized wakeup behavior. /// -/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table -/// /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] /// that customizes the behavior of the `RawWaker`. +/// +/// `RawWaker`s are unsafe to use. +/// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. +/// +/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table +/// [`Wake`]: ../../alloc/task/trait.Wake.html #[derive(PartialEq, Debug)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct RawWaker { @@ -355,8 +359,12 @@ impl<'a> ContextBuilder<'a> { /// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker /// unnecessarily if the two wakers [wake the same task](Self::will_wake). /// +/// Constructing a `Waker` from a [`RawWaker`] is unsafe. +/// Implementing the [`Wake`] trait is a safe alternative that requires memory allocation. +/// /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending +/// [`Wake`]: ../../alloc/task/trait.Wake.html #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 #[stable(feature = "futures_api", since = "1.36.0")] pub struct Waker { @@ -438,9 +446,15 @@ impl Waker { /// Creates a new `Waker` from [`RawWaker`]. /// + /// # Safety + /// /// The behavior of the returned `Waker` is undefined if the contract defined /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. - /// Therefore this method is unsafe. + /// + /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the + /// cost of a required heap allocation.) + /// + /// [`Wake`]: ../../alloc/task/trait.Wake.html #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] diff --git a/library/std/build.rs b/library/std/build.rs index 35b183c47d791..ee3f3612d2e0f 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -7,7 +7,9 @@ fn main() { let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); - + if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() { + println!("cargo:rustc-cfg=netbsd10"); + } if target_os == "linux" || target_os == "android" || target_os == "netbsd" diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index b8873a3b59a0b..6d068613f8f30 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -13,7 +13,7 @@ use crate::sync::Once; /// /// # Examples /// -/// Using `OnceCell` to store a function’s previously computed value (a.k.a. +/// Using `OnceLock` to store a function’s previously computed value (a.k.a. /// ‘lazy static’ or ‘memoizing’): /// /// ``` diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs index 1dba1ccf64e68..5c32957bc519c 100644 --- a/library/std/src/sys/pal/unix/rand.rs +++ b/library/std/src/sys/pal/unix/rand.rs @@ -62,7 +62,7 @@ mod imp { unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) } } - #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd"))] + #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))] fn getrandom(buf: &mut [u8]) -> libc::ssize_t { unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) } } @@ -72,7 +72,8 @@ mod imp { target_os = "android", target_os = "espidf", target_os = "horizon", - target_os = "freebsd" + target_os = "freebsd", + netbsd10 )))] fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool { false @@ -83,7 +84,8 @@ mod imp { target_os = "android", target_os = "espidf", target_os = "horizon", - target_os = "freebsd" + target_os = "freebsd", + netbsd10 ))] fn getrandom_fill_bytes(v: &mut [u8]) -> bool { use crate::sync::atomic::{AtomicBool, Ordering}; @@ -230,7 +232,7 @@ mod imp { } // FIXME: once the 10.x release becomes the minimum, this can be dropped for simplification. -#[cfg(target_os = "netbsd")] +#[cfg(all(target_os = "netbsd", not(netbsd10)))] mod imp { use crate::ptr; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 36f9ee6aff665..0e9a9791fb251 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -86,6 +86,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (Some(Mode::Std), "no_global_oom_handling", None), (Some(Mode::Std), "no_rc", None), (Some(Mode::Std), "no_sync", None), + (Some(Mode::Std), "netbsd10", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx"])), diff --git a/tests/mir-opt/issue_120925_unsafefncast.rs b/tests/mir-opt/issue_120925_unsafefncast.rs new file mode 100644 index 0000000000000..f80ae66efdae3 --- /dev/null +++ b/tests/mir-opt/issue_120925_unsafefncast.rs @@ -0,0 +1,25 @@ +// Verify that we do not ICE when attempting to interpret casts between fn types. +// skip-filecheck + +static FOO: fn() = || assert_ne!(42, 43); +static BAR: fn(i32, i32) = |a, b| assert_ne!(a, b); + +fn main() { + FOO(); + + let bar: unsafe fn(i32, i32) = BAR; + + let f: fn() = || {}; + f(); + + f(); + + f(); + + let g: fn(i32) = |i| assert_eq!(i, 2); + g(2); + + g(2); + + g(2); +} diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr index 6bc38811f1b5f..4a50ec8d0d5ac 100644 --- a/tests/ui/asm/inline-syntax.arm.stderr +++ b/tests/ui/asm/inline-syntax.arm.stderr @@ -13,7 +13,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:35:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^ @@ -25,7 +25,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:42:15 + --> $DIR/inline-syntax.rs:39:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^ @@ -37,7 +37,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:46:15 + --> $DIR/inline-syntax.rs:43:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^ @@ -49,7 +49,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:50:15 + --> $DIR/inline-syntax.rs:47:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^ @@ -61,7 +61,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:54:15 + --> $DIR/inline-syntax.rs:51:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^ @@ -73,7 +73,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:61:13 + --> $DIR/inline-syntax.rs:58:13 | LL | .intel_syntax noprefix | ^ diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr index 4926293bb88ad..ada3f4891d3ac 100644 --- a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr +++ b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr @@ -15,7 +15,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:35:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^ @@ -27,7 +27,7 @@ LL | .intel_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:42:15 + --> $DIR/inline-syntax.rs:39:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^ @@ -39,7 +39,7 @@ LL | .intel_syntax aaa noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:46:15 + --> $DIR/inline-syntax.rs:43:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^ @@ -51,7 +51,7 @@ LL | .att_syntax noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:50:15 + --> $DIR/inline-syntax.rs:47:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^ @@ -63,7 +63,7 @@ LL | .att_syntax bbb noprefix | ^ error: unknown directive - --> $DIR/inline-syntax.rs:54:15 + --> $DIR/inline-syntax.rs:51:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^ @@ -75,7 +75,7 @@ LL | .intel_syntax noprefix; nop | ^ error: unknown directive - --> $DIR/inline-syntax.rs:61:13 + --> $DIR/inline-syntax.rs:58:13 | LL | .intel_syntax noprefix | ^ diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs index 9398a87df6273..a8c6c71b805f2 100644 --- a/tests/ui/asm/inline-syntax.rs +++ b/tests/ui/asm/inline-syntax.rs @@ -2,14 +2,11 @@ //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64] check-pass //[x86_64] needs-llvm-components: x86 -//[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu -//[x86_64_allowed] check-pass -//[x86_64_allowed] needs-llvm-components: x86 //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf //[arm] build-fail //[arm] needs-llvm-components: arm //[arm] ignore-llvm-version: 18 - 99 -// Newer LLVM produces extra error notes. +//Newer LLVM produces extra error notes. //[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf //[arm_llvm_18] build-fail //[arm_llvm_18] needs-llvm-components: arm diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr index b54b3560447c9..66dc37f3089e1 100644 --- a/tests/ui/asm/inline-syntax.x86_64.stderr +++ b/tests/ui/asm/inline-syntax.x86_64.stderr @@ -1,5 +1,5 @@ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:70:14 + --> $DIR/inline-syntax.rs:67:14 | LL | global_asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop"); = note: `#[warn(bad_asm_style)]` on by default warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:38:15 + --> $DIR/inline-syntax.rs:35:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:42:15 + --> $DIR/inline-syntax.rs:39:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:46:15 + --> $DIR/inline-syntax.rs:43:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - --> $DIR/inline-syntax.rs:50:15 + --> $DIR/inline-syntax.rs:47:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:54:15 + --> $DIR/inline-syntax.rs:51:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ warning: avoid using `.intel_syntax`, Intel syntax is the default - --> $DIR/inline-syntax.rs:61:13 + --> $DIR/inline-syntax.rs:58:13 | LL | .intel_syntax noprefix | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.fixed b/tests/ui/borrowck/copy-suggestion-region-vid.fixed new file mode 100644 index 0000000000000..ec16469757a71 --- /dev/null +++ b/tests/ui/borrowck/copy-suggestion-region-vid.fixed @@ -0,0 +1,18 @@ +// run-rustfix +pub struct DataStruct(); + +pub struct HelperStruct<'n> { + pub helpers: [Vec<&'n i64>; 2], + pub is_empty: bool, +} + +impl DataStruct { + pub fn f(&self) -> HelperStruct { + let helpers = [vec![], vec![]]; + + HelperStruct { helpers: helpers.clone(), is_empty: helpers[0].is_empty() } + //~^ ERROR borrow of moved value + } +} + +fn main() {} diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.rs b/tests/ui/borrowck/copy-suggestion-region-vid.rs index 3c5b887ce17bd..f95c6b03e014a 100644 --- a/tests/ui/borrowck/copy-suggestion-region-vid.rs +++ b/tests/ui/borrowck/copy-suggestion-region-vid.rs @@ -1,4 +1,4 @@ -//@run-rustfix +// run-rustfix pub struct DataStruct(); pub struct HelperStruct<'n> { diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr index d5c5f76b90a01..7cb85d5279d0d 100644 --- a/tests/ui/consts/issue-89088.stderr +++ b/tests/ui/consts/issue-89088.stderr @@ -9,9 +9,4 @@ LL | FOO => todo!(), = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -note: the lint level is defined here - --> $DIR/issue-89088.rs:5:10 - | -LL | #![allow(indirect_structural_match)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 3c474d19d1d05..4a119f673c8ee 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -182,7 +182,7 @@ LL | type H = Fn(u8) -> (u8)::Output; = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | type H = (u8)>::Output; | ++++ + diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index 65d44604dc9fc..711bfa188ecd8 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #[deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn function(x: &dyn SomeTrait, y: Box) { | +++ @@ -24,7 +24,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn function(x: &SomeTrait, y: Box) { | +++ @@ -37,7 +37,7 @@ LL | let _x: &SomeTrait = todo!(); | = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let _x: &dyn SomeTrait = todo!(); | +++ diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr index 0b194cb8364c6..41298cc73c818 100644 --- a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | ::fmt(self, f) | +++ diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index 84aaedf183815..3cb3af89bfc25 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -7,7 +7,7 @@ LL | fn ice() -> impl AsRef { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn ice() -> impl AsRef { | +++ diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index 71d642109ac8c..8b427b692a79c 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -7,7 +7,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let x: u8 = ::bitor(0 as u8, 0 as u8); | ++++ + @@ -35,7 +35,7 @@ LL | let g = BitXor::bitor; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let g = ::bitor; | ++++ + diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr index 5ae1ec7cac8f8..71581e96844ee 100644 --- a/tests/ui/issues/issue-58734.stderr +++ b/tests/ui/issues/issue-58734.stderr @@ -7,7 +7,7 @@ LL | Trait::nonexistent(()); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | ::nonexistent(()); | ++++ + diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr index bfa7459ab4a39..d0906a6fa74f4 100644 --- a/tests/ui/issues/issue-86756.stderr +++ b/tests/ui/issues/issue-86756.stderr @@ -21,7 +21,7 @@ LL | eq:: = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | eq:: | +++ diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index c5d72707f80e8..da1d9f248a01f 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -7,7 +7,7 @@ LL | let _: Dyn::Ty; = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let _: ::Ty; | ++++ + @@ -26,7 +26,7 @@ LL | Dyn::func(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | ::func(); | ++++ + @@ -39,7 +39,7 @@ LL | ::Dyn::func(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | ::func(); | ++++++ ++ @@ -52,7 +52,7 @@ LL | Dyn::CONST; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | ::CONST; | ++++ + diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index e9b7b248e612f..388dc6160cb95 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -7,7 +7,7 @@ LL | pub fn function(_x: Box) {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: requested on the command line with `--force-warn bare-trait-objects` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index e569b2f9f1ae9..a037fb671af29 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -7,7 +7,7 @@ LL | pub fn function(_x: Box) {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: requested on the command line with `--force-warn bare-trait-objects` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index c971e4d0d4d21..a74cda2239f50 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index 97b8694984dd7..c9472a3b9b9d3 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index cd030cc1fcd18..558d5cbb53156 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -8,7 +8,7 @@ LL | pub fn function(_x: Box) {} = note: for more information, see = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | pub fn function(_x: Box) {} | +++ diff --git a/tests/ui/lint/future-incompat-json-test.stderr b/tests/ui/lint/future-incompat-json-test.stderr index 18fc3f17f0020..f33a5cab6ba09 100644 --- a/tests/ui/lint/future-incompat-json-test.stderr +++ b/tests/ui/lint/future-incompat-json-test.stderr @@ -1,10 +1,7 @@ -{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` +{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` --> $DIR/future-incompat-json-test.rs:9:9 | LL | let x = 1; | ^ help: if this is intentional, prefix it with an underscore: `_x` - | - = note: `-A unused-variables` implied by `-A unused` - = help: to override `-A unused` add `#[allow(unused_variables)]` "}}]} diff --git a/tests/ui/lint/future-incompat-test.stderr b/tests/ui/lint/future-incompat-test.stderr index 2951f904fb5e8..f24e1c7aba452 100644 --- a/tests/ui/lint/future-incompat-test.stderr +++ b/tests/ui/lint/future-incompat-test.stderr @@ -4,7 +4,4 @@ warning: unused variable: `x` | LL | let x = 1; | ^ help: if this is intentional, prefix it with an underscore: `_x` - | - = note: `-A unused-variables` implied by `-A unused` - = help: to override `-A unused` add `#[allow(unused_variables)]` diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr index c60120061643d..ea72ef84b9dae 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr @@ -60,11 +60,6 @@ LL | foo!(first) = note: for more information, see issue #79813 = note: macro invocations at the end of a block are treated as expressions = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` -note: the lint level is defined here - --> $DIR/semicolon-in-expressions-from-macros.rs:24:13 - | -LL | #[allow(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: @@ -79,11 +74,6 @@ LL | let _ = foo!(second); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 -note: the lint level is defined here - --> $DIR/semicolon-in-expressions-from-macros.rs:29:13 - | -LL | #[allow(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: @@ -98,11 +88,6 @@ LL | let _ = foo!(third); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 -note: the lint level is defined here - --> $DIR/semicolon-in-expressions-from-macros.rs:32:13 - | -LL | #[allow(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: @@ -117,11 +102,6 @@ LL | let _ = foo!(fourth); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 -note: the lint level is defined here - --> $DIR/semicolon-in-expressions-from-macros.rs:37:13 - | -LL | #[allow(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr index 41c09b7df6289..70e7ea535284d 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr @@ -7,7 +7,7 @@ LL | fn id(f: Copy) -> usize { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn id(f: dyn Copy) -> usize { | +++ @@ -21,7 +21,7 @@ LL | fn id(f: Copy) -> usize { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn id(f: dyn Copy) -> usize { | +++ diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr index a36e2519c804d..f499e2d946ffe 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr @@ -7,7 +7,7 @@ LL | trait B { fn f(a: A) -> A; } = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait B { fn f(a: dyn A) -> A; } | +++ @@ -20,7 +20,7 @@ LL | trait B { fn f(a: A) -> A; } | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait B { fn f(a: A) -> dyn A; } | +++ @@ -33,7 +33,7 @@ LL | trait A { fn g(b: B) -> B; } | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait A { fn g(b: dyn B) -> B; } | +++ @@ -46,7 +46,7 @@ LL | trait A { fn g(b: B) -> B; } | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait A { fn g(b: B) -> dyn B; } | +++ @@ -60,7 +60,7 @@ LL | trait B { fn f(a: A) -> A; } = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait B { fn f(a: dyn A) -> A; } | +++ @@ -96,7 +96,7 @@ LL | trait A { fn g(b: B) -> B; } = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | trait A { fn g(b: dyn B) -> B; } | +++ diff --git a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr index 7c7af9682800f..3939c06eabe5b 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr @@ -19,7 +19,7 @@ LL | fn call_this(f: F) : Fn(&str) + call_that {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn call_this(f: F) : dyn Fn(&str) + call_that {} | +++ diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr index 274d5a639a43b..f795e910d2152 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn ord_prefer_dot(s: String) -> dyn Ord { | +++ diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index 5e07a3fe6c740..3134746b930ac 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -25,7 +25,7 @@ LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let _: Box Trait<'a>)>; | +++ @@ -49,7 +49,7 @@ LL | let _: Box Trait<'a>) + (Obj)>; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let _: Box Trait<'a>) + (Obj)>; | +++ @@ -73,7 +73,7 @@ LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | +++ diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 59b454d398195..2a1cd3a7aa4bb 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -20,10 +20,4 @@ LL | if let CONSTANT = &&MyType { = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -note: the lint level is defined here - --> $DIR/const-partial_eq-fallback-ice.rs:1:10 - | -LL | #![allow(warnings)] - | ^^^^^^^^ - = note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]` diff --git a/tests/ui/proc-macro/generate-mod.stderr b/tests/ui/proc-macro/generate-mod.stderr index db629b5b5e239..cbe6b14ca9af5 100644 --- a/tests/ui/proc-macro/generate-mod.stderr +++ b/tests/ui/proc-macro/generate-mod.stderr @@ -139,11 +139,6 @@ LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 -note: the lint level is defined here - --> $DIR/generate-mod.rs:30:10 - | -LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: @@ -155,10 +150,5 @@ LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83583 -note: the lint level is defined here - --> $DIR/generate-mod.rs:30:10 - | -LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs new file mode 100644 index 0000000000000..614fc27b77187 --- /dev/null +++ b/tests/ui/suggestions/issue-116434-2015.rs @@ -0,0 +1,23 @@ +trait Foo { + type Clone; + fn foo() -> Clone; + //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| ERROR the trait `Clone` cannot be made into an object [E0038] +} + +trait DbHandle: Sized {} + +trait DbInterface { + type DbHandle; + fn handle() -> DbHandle; + //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| ERROR the trait `DbHandle` cannot be made into an object [E0038] +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr new file mode 100644 index 0000000000000..2d87029b6eb11 --- /dev/null +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -0,0 +1,81 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:3:17 + | +LL | fn foo() -> Clone; + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: if this is an object-safe trait, use `dyn` + | +LL | fn foo() -> dyn Clone; + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:15:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is an object-safe trait, use `dyn` + | +LL | fn handle() -> dyn DbHandle; + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:3:17 + | +LL | fn foo() -> Clone; + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: if this is an object-safe trait, use `dyn` + | +LL | fn foo() -> dyn Clone; + | +++ + +error[E0038]: the trait `Clone` cannot be made into an object + --> $DIR/issue-116434-2015.rs:3:17 + | +LL | fn foo() -> Clone; + | ^^^^^ `Clone` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:15:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: if this is an object-safe trait, use `dyn` + | +LL | fn handle() -> dyn DbHandle; + | +++ + +error[E0038]: the trait `DbHandle` cannot be made into an object + --> $DIR/issue-116434-2015.rs:15:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ `DbHandle` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-116434-2015.rs:11:17 + | +LL | trait DbHandle: Sized {} + | -------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 2 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs new file mode 100644 index 0000000000000..74c30e0cc1fbe --- /dev/null +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -0,0 +1,17 @@ +// edition:2021 + +trait Foo { + type Clone; + fn foo() -> Clone; + //~^ ERROR the trait `Clone` cannot be made into an object [E0038] +} + +trait DbHandle: Sized {} + +trait DbInterface { + type DbHandle; + fn handle() -> DbHandle; + //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr new file mode 100644 index 0000000000000..43ad82d484a66 --- /dev/null +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -0,0 +1,26 @@ +error[E0038]: the trait `Clone` cannot be made into an object + --> $DIR/issue-116434-2021.rs:5:17 + | +LL | fn foo() -> Clone; + | ^^^^^ `Clone` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error[E0038]: the trait `DbHandle` cannot be made into an object + --> $DIR/issue-116434-2021.rs:13:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ `DbHandle` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-116434-2021.rs:9:17 + | +LL | trait DbHandle: Sized {} + | -------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index 754d02b1c021b..084b0cbeef292 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | bar: Box, | +++ @@ -24,7 +24,7 @@ LL | pub struct Foo { | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | dyn pub struct Foo { | +++ diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr index ffd505fffb48e..0098814f81e78 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr @@ -40,7 +40,7 @@ LL | impl<'a, T> Struct for Trait<'a, T> {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ diff --git a/tests/ui/trait-bounds/suggest-maybe-sized-bound.rs b/tests/ui/trait-bounds/suggest-maybe-sized-bound.rs new file mode 100644 index 0000000000000..15aa27349aa91 --- /dev/null +++ b/tests/ui/trait-bounds/suggest-maybe-sized-bound.rs @@ -0,0 +1,20 @@ +// issue: 120878 +fn main() { + struct StructA { + _marker: std::marker::PhantomData (A, B)>, + } + + struct StructB { + a: StructA, + //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277] + } + + trait Trait { + type P; + } + + impl Trait for () { + type P = [u8]; + //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277] + } +} diff --git a/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr new file mode 100644 index 0000000000000..4ce936582f43d --- /dev/null +++ b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr @@ -0,0 +1,37 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-maybe-sized-bound.rs:8:12 + | +LL | a: StructA, + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `StructA` + --> $DIR/suggest-maybe-sized-bound.rs:3:23 + | +LL | struct StructA { + | ^^^^^ required by the implicit `Sized` requirement on this type parameter in `StructA` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct StructA { + | ++++++++ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-maybe-sized-bound.rs:17:21 + | +LL | type P = [u8]; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Trait::P` + --> $DIR/suggest-maybe-sized-bound.rs:13:9 + | +LL | type P; + | ^^^^^^^^^^ required by this bound in `Trait::P` +help: consider relaxing the implicit `Sized` restriction + | +LL | type P: ?Sized; + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 6d56851bf3495..f1e7a28654a74 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -7,7 +7,7 @@ LL | fn foo(_x: Foo + Send) { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | fn foo(_x: dyn Foo + Send) { | +++ diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index adba5830b10e1..653ce05d28574 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -36,8 +36,8 @@ LL | pub trait Bar: Foo + Sized { | +++++++ help: consider relaxing the implicit `Sized` restriction | -LL | pub trait Foo { - | ++++++++ +LL | pub trait Foo { + | ++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-28576.rs:5:16 @@ -56,8 +56,8 @@ LL | ) where Self: Sized; | +++++++++++++++++ help: consider relaxing the implicit `Sized` restriction | -LL | pub trait Foo { - | ++++++++ +LL | pub trait Foo { + | ++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-33140-hack-boundaries.stderr b/tests/ui/traits/issue-33140-hack-boundaries.stderr index 06e1dfd372751..d9c4efbb721c7 100644 --- a/tests/ui/traits/issue-33140-hack-boundaries.stderr +++ b/tests/ui/traits/issue-33140-hack-boundaries.stderr @@ -77,9 +77,4 @@ LL | impl Trait0 for dyn Send {} | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #56484 -note: the lint level is defined here - --> $DIR/issue-33140-hack-boundaries.rs:2:10 - | -LL | #![allow(order_dependent_trait_objects)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr index b5e8e88676c61..3614348ceedc7 100644 --- a/tests/ui/traits/unspecified-self-in-trait-ref.stderr +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -7,7 +7,7 @@ LL | let a = Foo::lol(); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see = note: `#[warn(bare_trait_objects)]` on by default -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let a = ::lol(); | ++++ + @@ -26,7 +26,7 @@ LL | let b = Foo::<_>::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let b = >::lol(); | ++++ + @@ -45,7 +45,7 @@ LL | let c = Bar::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let c = ::lol(); | ++++ + @@ -64,7 +64,7 @@ LL | let d = Bar::::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let d = >::lol(); | ++++ + @@ -83,7 +83,7 @@ LL | let e = Bar::::lol(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see -help: use `dyn` +help: if this is an object-safe trait, use `dyn` | LL | let e = >::lol(); | ++++ +