diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e86c7f15e9679..c2069432e6f8e 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -36,6 +36,7 @@ even other Rust compilers, such as rust-analyzer! */ +use std::cmp::min; use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; @@ -1060,14 +1061,8 @@ impl Align { /// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller. #[inline] pub fn max_for_target(tdl: &TargetDataLayout) -> Align { - let pointer_bits = tdl.pointer_size().bits(); - if let Ok(pointer_bits) = u8::try_from(pointer_bits) - && pointer_bits <= Align::MAX.pow2 - { - Align { pow2: pointer_bits - 1 } - } else { - Align::MAX - } + let pointer_bits = u8::try_from(tdl.pointer_size().bits()).unwrap(); + min(Align { pow2: pointer_bits - 1 }, Align::MAX) } #[inline] diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 1e336f1e4509d..15e3cf28aac32 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{ Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DesugaringKind, Span, kw, sym}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use rustc_trait_selection::error_reporting::traits::call_kind::CallKind; @@ -574,24 +574,6 @@ fn suggest_rewrite_if_let( } impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { - fn free_region_constraint_info( - &self, - borrow_region: RegionVid, - outlived_region: RegionVid, - ) -> (ConstraintCategory<'tcx>, bool, Span, Option, Vec>) - { - let (blame_constraint, path) = self.regioncx.best_blame_constraint( - borrow_region, - NllRegionVariableOrigin::FreeRegion, - outlived_region, - ); - let BlameConstraint { category, from_closure, span, .. } = blame_constraint; - - let outlived_fr_name = self.give_region_a_name(outlived_region); - - (category, from_closure, span, outlived_fr_name, path) - } - /// Returns structured explanation for *why* the borrow contains the /// point from `location`. This is key for the "3-point errors" /// [described in the NLL RFC][d]. @@ -707,9 +689,14 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // Here, under NLL: no cause was found. Under polonius: no cause was found, or a // boring local was found, which we ignore like NLLs do to match its diagnostics. if let Some(region) = self.regioncx.to_error_region_vid(borrow_region_vid) { - let (category, from_closure, span, region_name, path) = - self.free_region_constraint_info(borrow_region_vid, region); - if let Some(region_name) = region_name { + let (blame_constraint, path) = self.regioncx.best_blame_constraint( + borrow_region_vid, + NllRegionVariableOrigin::FreeRegion, + region, + ); + let BlameConstraint { category, from_closure, span, .. } = blame_constraint; + + if let Some(region_name) = self.give_region_a_name(region) { let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); BorrowExplanation::MustBeValidFor { category, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 467eceea221c8..b37fb213d945a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -421,6 +421,17 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { source_info.span, ) } + AssertKind::NullReferenceConstructed => { + let location = fx.get_caller_location(source_info).load_scalar(fx); + + codegen_panic_inner( + fx, + rustc_hir::LangItem::PanicNullReferenceConstructed, + &[location], + *unwind, + source_info.span, + ) + } AssertKind::InvalidEnumConstruction(source) => { let source = codegen_operand(fx, source).load_scalar(fx); let location = fx.get_caller_location(source_info).load_scalar(fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0173b84a4d9a1..fad93de43b272 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -789,6 +789,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `#[track_caller]` adds an implicit argument. (LangItem::PanicNullPointerDereference, vec![location]) } + AssertKind::NullReferenceConstructed => { + // It's `fn panic_null_reference_constructed()`, + // `#[track_caller]` adds an implicit argument. + (LangItem::PanicNullReferenceConstructed, vec![location]) + } AssertKind::InvalidEnumConstruction(source) => { let source = self.codegen_operand(bx, source).immediate(); // It's `fn panic_invalid_enum_construction(source: u128)`, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index b4a97c0b137c9..e7e1dd2ec0fb0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -772,6 +772,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { found: eval_to_int(found)?, }, NullPointerDereference => NullPointerDereference, + NullReferenceConstructed => NullReferenceConstructed, InvalidEnumConstruction(source) => InvalidEnumConstruction(eval_to_int(source)?), }; Err(ConstEvalErrKind::AssertFailure(err)).into() diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 1c6b623bbf267..1b6c948657e0d 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,4 +1,5 @@ use rustc_abi::{BackendRepr, FieldIdx, VariantIdx}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; use rustc_middle::traits::ObligationCause; @@ -17,13 +18,15 @@ use crate::interpret::{ intern_const_alloc_recursive, }; -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn branches<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, field_count: usize, variant: Option, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let place = match variant { Some(variant) => ecx.project_downcast(place, variant).unwrap(), @@ -45,7 +48,7 @@ fn branches<'tcx>( for i in 0..field_count { let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap(); - let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; + let valtree = const_to_valtree_inner(ecx, &field, num_nodes, visited, settled)?; branches.push(ty::Const::new_value(*ecx.tcx, valtree, field.layout.ty)); } @@ -57,39 +60,53 @@ fn branches<'tcx>( Ok(ty::ValTree::from_branches(*ecx.tcx, branches)) } -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn slice_branches<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {place:?}")); let mut elems = Vec::with_capacity(n as usize); for i in 0..n { let place_elem = ecx.project_index(place, i).unwrap(); - let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; + let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes, visited, settled)?; elems.push(ty::Const::new_value(*ecx.tcx, valtree, place_elem.layout.ty)); } Ok(ty::ValTree::from_branches(*ecx.tcx, elems)) } -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn const_to_valtree_inner<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let tcx = *ecx.tcx; let ty = place.layout.ty; debug!("ty kind: {:?}", ty.kind()); + if let Some(&result) = settled.get(place) { + return result; + } + + if visited.contains(place) { + return Err(ValTreeCreationError::CyclicConst); + } + if *num_nodes >= VALTREE_MAX_NODES { return Err(ValTreeCreationError::NodesOverflow); } - match ty.kind() { + visited.insert(place.clone()); + + let result = ensure_sufficient_stack(|| match ty.kind() { ty::FnDef(..) => { *num_nodes += 1; Ok(ty::ValTree::zst(tcx)) @@ -108,7 +125,7 @@ fn const_to_valtree_inner<'tcx>( // Since the returned valtree does not contain the type or layout, we can just // switch to the base type. place.layout = ecx.layout_of(*base).unwrap(); - ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes)) + const_to_valtree_inner(ecx, &place, num_nodes, visited, settled) } ty::RawPtr(_, _) => { @@ -120,16 +137,16 @@ fn const_to_valtree_inner<'tcx>( // We could allow wide raw pointers where both sides are integers in the future, // but for now we reject them. if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) { - return Err(ValTreeCreationError::NonSupportedType(ty)); + Err(ValTreeCreationError::NonSupportedType(ty)) + } else { + let val = val.to_scalar(); + // We are in the CTFE machine, so ptr-to-int casts will fail. + // This can only be `Ok` if `val` already is an integer. + match val.try_to_scalar_int() { + Ok(val) => Ok(ty::ValTree::from_scalar_int(tcx, val)), + Err(_) => Err(ValTreeCreationError::NonSupportedType(ty)), + } } - let val = val.to_scalar(); - // We are in the CTFE machine, so ptr-to-int casts will fail. - // This can only be `Ok` if `val` already is an integer. - let Ok(val) = val.try_to_scalar_int() else { - return Err(ValTreeCreationError::NonSupportedType(ty)); - }; - // It's just a ScalarInt! - Ok(ty::ValTree::from_scalar_int(tcx, val)) } // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to @@ -138,33 +155,39 @@ fn const_to_valtree_inner<'tcx>( ty::Ref(_, _, _) => { let derefd_place = ecx.deref_pointer(place).report_err()?; - const_to_valtree_inner(ecx, &derefd_place, num_nodes) + const_to_valtree_inner(ecx, &derefd_place, num_nodes, visited, settled) } - ty::Str | ty::Slice(_) | ty::Array(_, _) => slice_branches(ecx, place, num_nodes), + ty::Str | ty::Slice(_) | ty::Array(_, _) => { + slice_branches(ecx, place, num_nodes, visited, settled) + } // Trait objects are not allowed in type level constants, as we have no concept for // resolving their backing type, even if we can do that at const eval time. We may // hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future, // but it is unclear if this is useful. ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)), - ty::Tuple(elem_tys) => branches(ecx, place, elem_tys.len(), None, num_nodes), + ty::Tuple(elem_tys) => { + branches(ecx, place, elem_tys.len(), None, num_nodes, visited, settled) + } ty::Adt(def, _) => { if def.is_union() { - return Err(ValTreeCreationError::NonSupportedType(ty)); + Err(ValTreeCreationError::NonSupportedType(ty)) } else if def.variants().is_empty() { bug!("uninhabited types should have errored and never gotten converted to valtree") + } else { + let variant = ecx.read_discriminant(place).report_err()?; + branches( + ecx, + place, + def.variant(variant).fields.len(), + def.is_enum().then_some(variant), + num_nodes, + visited, + settled, + ) } - - let variant = ecx.read_discriminant(place).report_err()?; - branches( - ecx, - place, - def.variant(variant).fields.len(), - def.is_enum().then_some(variant), - num_nodes, - ) } // FIXME(oli-obk): we could look behind opaque types @@ -186,7 +209,11 @@ fn const_to_valtree_inner<'tcx>( | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)), - } + }); + + visited.remove(place); + settled.insert(place.clone(), result); + result } /// Valtrees don't store the `MemPlaceMeta` that all dynamically sized values have in the interpreter. @@ -257,7 +284,9 @@ pub(crate) fn eval_to_valtree<'tcx>( debug!(?place); let mut num_nodes = 0; - const_to_valtree_inner(&ecx, &place, &mut num_nodes) + let mut visited = FxHashSet::default(); + let mut settled = FxHashMap::default(); + const_to_valtree_inner(&ecx, &place, &mut num_nodes, &mut visited, &mut settled) } /// Converts a `ValTree` to a `ConstValue`, which is needed after mir diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 9c3f7789f9ed9..f0b6d0fb8dcc9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -309,6 +309,7 @@ language_item_table! { PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None; PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None; PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None; + PanicNullReferenceConstructed, sym::panic_null_reference_constructed, panic_null_reference_constructed, Target::Fn, GenericRequirement::None; PanicInvalidEnumConstruction, sym::panic_invalid_enum_construction, panic_invalid_enum_construction, Target::Fn, GenericRequirement::None; PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None; PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 2823b7ba4e22e..ae2695987ff13 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -144,6 +144,15 @@ pub(crate) struct InvalidConstInValtree { pub global_const_id: String, } +#[derive(Diagnostic)] +#[diag("constant {$global_const_id} cannot be used as pattern")] +#[note("constants whose type references itself cannot be used as patterns")] +pub(crate) struct CyclicConstInValtree { + #[primary_span] + pub span: Span, + pub global_const_id: String, +} + #[derive(Diagnostic)] #[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] pub(crate) struct Reentrant; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 7d9f6903d3ef0..e2c67b29943d6 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -105,6 +105,8 @@ pub enum ValTreeCreationError<'tcx> { InvalidConst, /// Values of this type, or this particular value, are not supported as valtrees. NonSupportedType(Ty<'tcx>), + /// Trying to valtree this constant would cause the valtree to have cycles. + CyclicConst, /// The error has already been handled by const evaluation. ErrorHandled(ErrorHandled), } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index accd00a8ebb51..2fe175dd363ce 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -232,6 +232,13 @@ impl<'tcx> TyCtxt<'tcx> { }); Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) } + ValTreeCreationError::CyclicConst => { + let handled = self.dcx().emit_err(error::CyclicConstInValtree { + span, + global_const_id: cid.display(self), + }); + Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) + } ValTreeCreationError::ErrorHandled(handled) => Err(handled), } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index d57e25af4a11a..5771019ddca46 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1046,6 +1046,7 @@ pub enum AssertKind { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: O, found: O }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(O), } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 3f66fe34af622..aaa0c257925dd 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -210,6 +210,7 @@ impl AssertKind { LangItem::PanicGenFnNonePanic } NullPointerDereference => LangItem::PanicNullPointerDereference, + NullReferenceConstructed => LangItem::PanicNullReferenceConstructed, InvalidEnumConstruction(_) => LangItem::PanicInvalidEnumConstruction, ResumedAfterDrop(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedDrop, ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { @@ -287,6 +288,7 @@ impl AssertKind { ) } NullPointerDereference => write!(f, "\"null pointer dereference occurred\""), + NullReferenceConstructed => write!(f, "\"null reference produced\""), InvalidEnumConstruction(source) => { write!(f, "\"trying to construct an enum from an invalid value {{}}\", {source:?}") } @@ -387,6 +389,7 @@ impl fmt::Display for AssertKind { write!(f, "coroutine resumed after panicking") } NullPointerDereference => write!(f, "null pointer dereference occurred"), + NullReferenceConstructed => write!(f, "null reference produced"), InvalidEnumConstruction(source) => { write!(f, "trying to construct an enum from an invalid value `{source:#?}`") } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 921c54b2828c2..22f2d5c1afcac 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -668,7 +668,7 @@ macro_rules! make_mir_visitor { OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => { self.visit_operand(op, location); } - ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => { + ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | NullReferenceConstructed | ResumedAfterDrop(_) => { // Nothing to visit } MisalignedPointerDereference { required, found } => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 41079d431edf9..01c5b87eda0d5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1128,6 +1128,23 @@ impl<'tcx> TypingEnv<'tcx> { Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis()) } + /// Ideally we just use `TypingMode::PostTypeckUntilBorrowck`. + /// But that's not compatible with the old solver yet. + /// + /// FIXME: this should not be needed in the long term. + pub fn post_typeck_until_borrowck_for_mir_build( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + ) -> TypingEnv<'tcx> { + if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingEnv::new(tcx.param_env(def_id.to_def_id()), ty::TypingMode::borrowck(tcx, def_id)) + } else { + // FIXME(#132279): We're in a body, we should use a typing + // mode which reveals the opaque types defined by that body. + TypingEnv::non_body_analysis(tcx, def_id) + } + } + pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey) -> TypingEnv<'tcx> { TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::PostAnalysis) } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index b6478fc9c8deb..4d63aaf0b1892 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -505,9 +505,15 @@ fn construct_fn<'tcx>( ); } - // FIXME(#132279): This should be able to reveal opaque - // types defined during HIR typeck. - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingMode::borrowck(tcx, fn_def) + } else { + // FIXME(#132279): This should be able to reveal opaque + // types defined during HIR typeck. + TypingMode::non_body_analysis() + }; + + let infcx = tcx.infer_ctxt().build(typing_mode); let mut builder = Builder::new( thir, infcx, @@ -587,9 +593,15 @@ fn construct_const<'a, 'tcx>( _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; - // FIXME(#132279): We likely want to be able to use the hidden types of - // opaques used by this function here. - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingMode::borrowck(tcx, def) + } else { + // FIXME(#132279): This should be able to reveal opaque + // types defined during HIR typeck. + TypingMode::non_body_analysis() + }; + + let infcx = tcx.infer_ctxt().build(typing_mode); let mut builder = Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 2197bbeab25cf..932e4af130459 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -968,8 +968,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { tcx: self.tcx, typeck_results, module: self.tcx.parent_module(self.hir_id).to_def_id(), - // FIXME(#132279): We're in a body, should handle opaques. - typing_env: rustc_middle::ty::TypingEnv::non_body_analysis(self.tcx, self.def_id), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build( + self.tcx, + self.def_id, + ), dropless_arena: &dropless_arena, match_lint_level: self.hir_id, whole_match_span: Some(rustc_span::Span::default()), diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index ac9f6e384cf04..26deba3f58c5a 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -27,8 +27,7 @@ pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), E tcx, thir, found_errors: Ok(()), - // FIXME(#132279): we're clearly in a body here. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), is_closure, caller_def_id: def, }; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index a5e5b9f7699b8..70e9129ffee3f 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1093,8 +1093,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { body_target_features, assignment_info: None, in_union_destructure: false, - // FIXME(#132279): we're clearly in a body here. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), inside_adt: false, warnings: &mut warnings, suggest_unsafe_block: true, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index eb8573dd5e886..8e654032e8b71 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -99,9 +99,7 @@ impl<'tcx> ThirBuildCx<'tcx> { Self { tcx, thir: Thir::new(body_type), - // FIXME(#132279): We're in a body, we should use a typing - // mode which reveals the opaque types defined by that body. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), typeck_results, body_owner: def.to_def_id(), apply_adjustments: !find_attr!(tcx, hir_id, CustomMir(..)), diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 7a38d9293724d..a757c96bd7f3d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -39,8 +39,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err tcx, thir: &*thir, typeck_results, - // FIXME(#132279): We're in a body, should handle opaques. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def_id), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def_id), hir_source: tcx.local_def_id_to_hir_id(def_id), let_source: LetSource::None, pattern_arena: &pattern_arena, diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index b589e2fff1569..beb26a20cd3f8 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -55,16 +55,19 @@ fn insert_null_check<'tcx>( const_: Const::Val(ConstValue::from_target_usize(0, &tcx), tcx.types.usize), })); - let pointee_should_be_checked = match context { + let (pointee_should_be_checked, assert_kind) = match context { // Borrows pointing to "null" are UB even if the pointee is a ZST. PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { // Pointer should be checked unconditionally. - Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::from_bool(tcx, true), - })) + ( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::from_bool(tcx, true), + })), + AssertKind::NullReferenceConstructed, + ) } // Other usages of null pointers only are UB if the pointee is not a ZST. _ => { @@ -79,7 +82,7 @@ fn insert_null_check<'tcx>( source_info, StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))), )); - Operand::Copy(pointee_should_be_checked) + (Operand::Copy(pointee_should_be_checked), AssertKind::NullPointerDereference) } }; @@ -119,9 +122,6 @@ fn insert_null_check<'tcx>( )); // Emit a PointerCheck that asserts on the condition and otherwise triggers - // a AssertKind::NullPointerDereference. - PointerCheck { - cond: Operand::Copy(is_ok), - assert_kind: Box::new(AssertKind::NullPointerDereference), - } + // the chosen AssertKind. + PointerCheck { cond: Operand::Copy(is_ok), assert_kind: Box::new(assert_kind) } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index bd608583d818c..9b18b22399ae8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -899,6 +899,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::NullPointerDereference => { push_mono_lang_item(self, LangItem::PanicNullPointerDereference); } + mir::AssertKind::NullReferenceConstructed => { + push_mono_lang_item(self, LangItem::PanicNullReferenceConstructed); + } mir::AssertKind::InvalidEnumConstruction(_) => { push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction); } diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index 79d11e54303f3..20682de5f4825 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -269,6 +269,7 @@ pub enum AssertMessage { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: Operand, found: Operand }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(Operand), } @@ -342,6 +343,7 @@ impl AssertMessage { Ok("misaligned pointer dereference") } AssertMessage::NullPointerDereference => Ok("null pointer dereference occurred"), + AssertMessage::NullReferenceConstructed => Ok("null reference produced"), AssertMessage::InvalidEnumConstruction(_) => { Ok("trying to construct an enum from an invalid value") } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index dec4044fd260b..3bef4d5cb38df 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -310,6 +310,9 @@ fn pretty_assert_message(writer: &mut W, msg: &AssertMessage) -> io::R AssertMessage::NullPointerDereference => { write!(writer, "\"null pointer dereference occurred\"") } + AssertMessage::NullReferenceConstructed => { + write!(writer, "\"null reference produced\"") + } AssertMessage::InvalidEnumConstruction(op) => { let pretty_op = pretty_operand(op); write!(writer, "\"trying to construct an enum from an invalid value {{}}\",{pretty_op}") diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index ae69f14faddd8..8cb3237bc4c83 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -369,6 +369,7 @@ macro_rules! make_mir_visitor { AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) | AssertMessage::NullPointerDereference + | AssertMessage::NullReferenceConstructed | AssertMessage::ResumedAfterDrop(_) => { //nothing to visit } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index c98a87d67458f..4293d1bede421 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -559,6 +559,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { } } AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference, + AssertKind::NullReferenceConstructed => { + crate::mir::AssertMessage::NullReferenceConstructed + } AssertKind::InvalidEnumConstruction(source) => { crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b99198d9ee8c4..8e23e290e9ab4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1536,6 +1536,7 @@ symbols! { panic_misaligned_pointer_dereference, panic_nounwind, panic_null_pointer_dereference, + panic_null_reference_constructed, panic_runtime, panic_str_2015, panic_unwind, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 9f5cfb39b9718..c4d04fe7d7f31 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4895,12 +4895,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.as_projection_clause() - && let Some(found) = failed_pred.skip_binder().term.as_type() + && let Some(found) = + failed_pred.map_bound(|pred| pred.term.as_type()).transpose().map(|term| { + self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + term, + ) + }) { type_diffs = vec![TypeError::Sorts(ty::error::ExpectedFound { - expected: where_pred - .skip_binder() - .projection_term + expected: self + .instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + where_pred.map_bound(|pred| pred.projection_term), + ) .expect_ty() .to_ty(self.tcx, ty::IsRigid::No), found, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 469eb4fc0630c..d6736852e088b 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -33,6 +33,7 @@ pub struct RegionDeps<'tcx> { } pub enum AutoTraitResult { + NoImpl, ExplicitImpl, PositiveImpl(A), NegativeImpl, @@ -80,6 +81,15 @@ impl<'tcx> AutoTraitFinder<'tcx> { ) -> AutoTraitResult { let tcx = self.tcx; + if tcx.next_trait_solver_globally() { + return self.find_auto_trait_generics_next_solver( + ty, + typing_env, + trait_did, + auto_trait_callback, + ); + } + let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); @@ -175,6 +185,79 @@ impl<'tcx> AutoTraitFinder<'tcx> { AutoTraitResult::PositiveImpl(auto_trait_callback(info)) } + fn find_auto_trait_generics_next_solver( + &self, + ty: Ty<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + trait_did: DefId, + mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A, + ) -> AutoTraitResult { + // When the new solver is enabled globally we keep things deliberately + // simple. The precise auto-trait synthesis depends on old-solver + // internals, so here we only synthesize a simple field-based auto-trait + // impl for ADTs. + // + // If the self type is not an ADT we return `NoImpl` instead of trying + // to do anything fancy. To decide whether to emit a negative impl, we + // replace the ADT's generic arguments with inference variables and + // check whether the auto trait can hold. A true error from that probe + // becomes a `NegativeImpl`, otherwise we continue on to emit the + // imprecise field-based impl. + // + // This keeps rustdoc from ICE-ing while `-Znext-solver=globally` is + // used for testing, even if the generated synthetic impls are less + // precise. + let tcx = self.tcx; + let ty::Adt(adt_def, args) = *ty.kind() else { + return AutoTraitResult::NoImpl; + }; + + let mut disqualifying_impl = None; + tcx.for_each_relevant_impl(trait_did, ty, |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }); + if let Some(impl_def_id) = disqualifying_impl { + debug!( + "find_auto_trait_generics({:?}): possible manual impl {impl_def_id:?} found, bailing", + ty::TraitRef::new(tcx, trait_did, [ty]), + ); + return AutoTraitResult::ExplicitImpl; + } + + let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let field_clauses = adt_def + .all_fields() + .map(|field| field.ty(tcx, args).skip_norm_wip()) + .filter(|field_ty| field_ty.has_non_region_param()) + .map(|field_ty| { + ty::TraitPredicate { + trait_ref: ty::TraitRef::new(tcx, trait_did, [field_ty]), + polarity: ty::PredicatePolarity::Positive, + } + .upcast(tcx) + }) + .collect::>>(); + let full_user_env = ty::ParamEnv::new( + tcx.mk_clauses_from_iter(orig_env.caller_bounds().iter().chain(field_clauses)), + ); + + let fresh_args = infcx.fresh_args_for_item(DUMMY_SP, adt_def.did()); + let fresh_ty = ty::EarlyBinder::bind(tcx, ty).instantiate(tcx, fresh_args).skip_norm_wip(); + let ocx = ObligationCtxt::new(&infcx); + ocx.register_bound(ObligationCause::dummy(), orig_env, fresh_ty, trait_did); + let errors = ocx.try_evaluate_obligations(); + if !errors.is_empty() { + return AutoTraitResult::NegativeImpl; + } + + let info = AutoTraitInfo { + full_user_env, + region_data: RegionConstraintData::default(), + vid_to_region: FxIndexMap::default(), + }; + AutoTraitResult::PositiveImpl(auto_trait_callback(info)) + } + /// The core logic responsible for computing the bounds for our synthesized impl. /// /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 41fff770374fb..1dd3019f68dfc 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -44,7 +44,6 @@ use crate::traits::{ /// bounds / where-clauses). #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct ImplHeader<'tcx> { - pub impl_def_id: DefId, pub impl_args: ty::GenericArgsRef<'tcx>, pub self_ty: Ty<'tcx>, pub trait_ref: Option>, @@ -207,7 +206,6 @@ fn fresh_impl_header<'tcx>( let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); ImplHeader { - impl_def_id, impl_args, self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(), trait_ref: is_of_trait diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3609dd1fe2e02..46790b620127b 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -305,6 +305,19 @@ fn panic_null_pointer_dereference() -> ! { ) } +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] +#[track_caller] +#[lang = "panic_null_reference_constructed"] // needed by codegen for panic on null reference formation +#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind +fn panic_null_reference_constructed() -> ! { + if cfg!(panic = "immediate-abort") { + super::intrinsics::abort() + } + + panic_nounwind_fmt(format_args!("null reference produced"), /* force_no_backtrace */ false) +} + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] #[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 1c3b6d01ed9d8..9426d9a684ef6 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -164,6 +164,14 @@ //! [`Once`]: crate::sync::Once //! [`OnceLock`]: crate::sync::OnceLock //! [`RwLock`]: crate::sync::RwLock +//! +//! ## Blocking guarantees +//! +//! Methods that are documented not to block will never block for an unbounded length of time. +//! That is, they may internally block through platform primitives but still "behave" like they are non-blocking. This difference is invisible to most programs. +//! +//! This is only of note to platforms which disallow blocking, such as multithreaded WebAssembly on the main thread. +//! None of the implementations in `std::sync` are guaranteed to be (or remain) non-blocking in this regard. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index a687f39431697..a34eabbccb1fc 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(Sender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -374,6 +376,11 @@ impl Sender { /// If called on a zero-capacity channel, this method will wait for a receive /// operation to appear on the other side of the channel. /// + /// If called on an unbounded channel, this method will never block in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees + /// /// # Examples /// /// ``` @@ -770,9 +777,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -917,7 +926,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for precise + /// guarantees on blocking.) /// /// If called on a zero-capacity channel, this method will receive a message only if there /// happens to be a send operation on the other side of the channel at the same time. @@ -929,6 +939,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index b74f84ff465c0..ad74ac2248878 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(SyncSender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -228,9 +230,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -590,7 +594,10 @@ impl Sender { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns [`Ok`]. /// - /// This method will never block the current thread. + /// This method will never block the caller in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -798,7 +805,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for + /// precise guarantees on blocking.) /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. @@ -807,6 +815,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index fe7e12cf1dc80..3ed08f4c5e933 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -110,6 +110,7 @@ fn synthesize_auto_trait_impl<'tcx>( (generics, ty::ImplPolarity::Negative) } + auto_trait::AutoTraitResult::NoImpl => return None, auto_trait::AutoTraitResult::ExplicitImpl => return None, }; diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 36b3705027aa1..76f39ae18b763 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "autocfg" @@ -149,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", - "shlex", + "shlex 1.3.0", ] [[package]] @@ -545,9 +545,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.4.1" +version = "6.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43ccdfe15a81ab0a8af639e90254227c9a46afd9c5f5b6ec7efaa345c4b0f00" +checksum = "f26569a2763497b7bd3fbd19374b774ea6038c5293678771259cd534d49740ff" dependencies = [ "derive_builder", "log", @@ -762,9 +762,9 @@ dependencies = [ [[package]] name = "mdbook-core" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fc1c4da7fd9e2e412f3891428f9468fab890ed159723ed0892bb85a049ac1c1" +checksum = "8725b7f8e94a5c40a00c907e4006301ba2fc06722de489a0cb19db1823fdf200" dependencies = [ "anyhow", "regex", @@ -776,9 +776,9 @@ dependencies = [ [[package]] name = "mdbook-driver" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2068566fc3c100cfd19f4a13e4e0eb4fdcd2250cfd0aa633ec25102b1c98d53e" +checksum = "485612ee2a91847760e742ce441673fa127306a43f44e666796f7d99d4592272" dependencies = [ "anyhow", "indexmap", @@ -791,7 +791,7 @@ dependencies = [ "regex", "serde", "serde_json", - "shlex", + "shlex 2.0.1", "tempfile", "toml 1.1.2+spec-1.1.0", "topological-sort", @@ -800,9 +800,9 @@ dependencies = [ [[package]] name = "mdbook-html" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ed2140251689f928615f0a5615413eb072eb28e003d179257aa4f034c95513" +checksum = "8d25933e4d7cbaa342db9ab9f414c2a09b1c59becb63ad344520370d822ab28a" dependencies = [ "anyhow", "ego-tree", @@ -846,9 +846,9 @@ dependencies = [ [[package]] name = "mdbook-markdown" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb3ca9eadf02ce206118a0b9c264718723d669b110c01a720fa9a0786f30642" +checksum = "9ca553aa4330b15fa2c706aef373bc714cc719513d1da73c17be3dba208b9aab" dependencies = [ "pulldown-cmark 0.13.4", "regex", @@ -857,9 +857,9 @@ dependencies = [ [[package]] name = "mdbook-preprocessor" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eff7b4afaafd664a649a03b8891ad8199aef359a35b911ad6c31acab38ed209" +checksum = "f8e75b08763e31982701d5b2680124bd4bd9bed4a4e1b5a499381320ccae199f" dependencies = [ "anyhow", "mdbook-core", @@ -869,9 +869,9 @@ dependencies = [ [[package]] name = "mdbook-renderer" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e607259410d53aa5cdaf5b6c1c6b3fd61f2e0f0523ebf457d34cd4f0b71e2a88" +checksum = "75d378308f820f05c6c89e4ec552a3c64a0cc10ccab7dcc93a2baa3bc714ea1b" dependencies = [ "anyhow", "mdbook-core", @@ -900,9 +900,9 @@ dependencies = [ [[package]] name = "mdbook-summary" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae8a734e5e35b0bc145b46d01fd27e266ba647dcdb9b8c907cb6a29eca9122b" +checksum = "2453622fa7236139365a9acd20314ab859ff747d57ba36ff0d476b64adc75cf8" dependencies = [ "anyhow", "mdbook-core", @@ -930,9 +930,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "miniz_oxide" @@ -1230,9 +1230,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -1253,9 +1253,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustbook" @@ -1345,6 +1345,7 @@ version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap", "itoa", "memchr", "serde", @@ -1407,6 +1408,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "simd-adler32" version = "0.3.9" diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index f981d09fbbee1..1551a289549a3 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" [dependencies] clap = { version = "4.0.32", features = ["cargo"] } -mdbook-driver = { version = "0.5.3", features = ["search"] } +mdbook-driver = { version = "0.5.4", features = ["search"] } mdbook-i18n-helpers = "0.4.0" mdbook-spec = { path = "../../doc/reference/tools/mdbook-spec" } mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" } diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index c0301bc44d175..dec492af8eb74 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit c0301bc44d175b9b2c5442b25049475c39d7700c +Subproject commit dec492af8eb74903879bd356648fc42d7aaf8555 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 9ad70538d1956..ebe3c04ea4cc4 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -244,6 +244,10 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ // tidy-alphabetical-start ("inferno", "CDDL-1.0"), ("option-ext", "MPL-2.0"), + ("terminfo", "WTFPL"), + ("wasite", "Apache-2.0 OR BSL-1.0 OR MIT"), + ("wezterm-bidi", "MIT AND Unicode-DFS-2016"), + ("whoami", "Apache-2.0 OR BSL-1.0 OR MIT"), // tidy-alphabetical-end ]; diff --git a/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs b/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs new file mode 100644 index 0000000000000..b48be49b29761 --- /dev/null +++ b/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs @@ -0,0 +1,7 @@ +//@ compile-flags: -Znext-solver=globally +//@ edition: 2021 +#![crate_name = "foo"] + +//@ has 'foo/struct.Foo.html' +//@ has - '//h3[@class="code-header"]' "impl<'a, 'b, T> Send for Foo<'a, 'b, T>where &'a T: Send, &'b T: Send" +pub struct Foo<'a, 'b, T: 'a + 'b>(&'a T, &'b T); diff --git a/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs b/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs new file mode 100644 index 0000000000000..145174a1961a5 --- /dev/null +++ b/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(auto_traits)] +#![crate_name = "foo"] + +pub auto trait Marker {} + +//@ has 'foo/struct.MyType.html' +//@ !has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 'Marker for MyType' +pub struct MyType(T); + +impl Marker for MyType {} diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs b/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs new file mode 100644 index 0000000000000..73dff8abf3a69 --- /dev/null +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs @@ -0,0 +1,16 @@ +// We used to ICE here while trying to synthesize auto trait impls +// with the next trait solver enabled globally. +//@ check-pass +//@ compile-flags: -Znext-solver=globally + +#![feature(const_default)] +#![feature(const_trait_impl)] + +pub struct Inner(T); + +pub struct Outer(Inner); + +impl Unpin for Inner +where + T: const std::default::Default, +{} diff --git a/tests/ui/issues/issue-33461.rs b/tests/ui/associated-types/self-type-projection-dyn-coerce.rs similarity index 73% rename from tests/ui/issues/issue-33461.rs rename to tests/ui/associated-types/self-type-projection-dyn-coerce.rs index 0de05c6687afb..81353e781d090 100644 --- a/tests/ui/issues/issue-33461.rs +++ b/tests/ui/associated-types/self-type-projection-dyn-coerce.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! This used to ICE as coercion to trait object didn't normalize associated +//! type. //@ run-pass + #![allow(unused_variables)] use std::marker::PhantomData; diff --git a/tests/ui/issues/issue-29857.rs b/tests/ui/coherence/error-type-coherence-no-ice.rs similarity index 71% rename from tests/ui/issues/issue-29857.rs rename to tests/ui/coherence/error-type-coherence-no-ice.rs index 9d4c9b2935a28..c66a02aa6cd27 100644 --- a/tests/ui/issues/issue-29857.rs +++ b/tests/ui/coherence/error-type-coherence-no-ice.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! This used to ICE during coherence on Error types. //@ check-pass use std::marker::PhantomData; diff --git a/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs new file mode 100644 index 0000000000000..64dd496ada58d --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs @@ -0,0 +1,20 @@ +//! Const generic variant of #144719 + +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Thing(&'static Thing); + +static X: Thing = Thing(&X); +const Y: &Thing = &X; + +fn foo() -> usize { 0 } + +fn main() { + foo::(); + //~^ ERROR constant main::{constant#0} cannot be used as pattern + //~| ERROR constant main::{constant#0} cannot be used as pattern +} diff --git a/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr new file mode 100644 index 0000000000000..2b278d6aba183 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr @@ -0,0 +1,19 @@ +error: constant main::{constant#0} cannot be used as pattern + --> $DIR/cyclic-const-generic-issue-144719.rs:17:11 + | +LL | foo::(); + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: constant main::{constant#0} cannot be used as pattern + --> $DIR/cyclic-const-generic-issue-144719.rs:17:11 + | +LL | foo::(); + | ^ + | + = note: constants whose type references itself cannot be used as patterns + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs b/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs new file mode 100644 index 0000000000000..cecf55d23e6b7 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs @@ -0,0 +1,13 @@ +//@ run-pass +//! Regression test: shared references to the same static (DAG) must not be +//! misidentified as cyclic during valtree construction. + +#[derive(PartialEq)] +struct Pair(&'static i32, &'static i32); + +static X: i32 = 42; +const P: Pair = Pair(&X, &X); + +fn main() { + if let P = P {} +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs new file mode 100644 index 0000000000000..39d22558b15dd --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs @@ -0,0 +1,24 @@ +//! Regression test for #144719: long reference cycles shouldn't +//! overflow the stack. +//@ rustc-env:RUST_MIN_STACK=3000000 + +#[derive(PartialEq, Copy, Clone)] +struct Thing(&'static Thing); + +const N: usize = 8000; +static A: Thing = Thing(&B[0]); +static B: [Thing; N] = { + let mut x = [Thing(&A); N]; + let mut i = 0; + while i < N - 1 { + x[i] = Thing(&B[i + 1]); + i += 1; + } + x +}; +const C: &Thing = &A; + +fn main() { + if let C = C {} + //~^ ERROR constant C cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr new file mode 100644 index 0000000000000..a549081a26475 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant C cannot be used as pattern + --> $DIR/cyclic-const-long-chain-issue-144719.rs:22:12 + | +LL | if let C = C {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs new file mode 100644 index 0000000000000..371a6a3811419 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs @@ -0,0 +1,14 @@ +//! Regression test for #144719: mutually recursive statics forming a +//! reference cycle caused a stack overflow during valtree construction. + +#[derive(PartialEq)] +struct Thing(&'static Thing); + +static A: Thing = Thing(&B); +static B: Thing = Thing(&A); +const C: &Thing = &A; + +fn main() { + if let C = C {} + //~^ ERROR constant C cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr new file mode 100644 index 0000000000000..e26505d9ce3ef --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant C cannot be used as pattern + --> $DIR/cyclic-const-mutual-issue-144719.rs:12:12 + | +LL | if let C = C {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs new file mode 100644 index 0000000000000..c54cb254b5cd8 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs @@ -0,0 +1,13 @@ +//! Regression test for #144719: using a self-referential static in a +//! pattern position caused a stack overflow during valtree construction. + +#[derive(PartialEq)] +struct Thing(&'static Thing); + +static X: Thing = Thing(&X); +const Y: &Thing = &X; + +fn main() { + if let Y = Y {} + //~^ ERROR constant Y cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr new file mode 100644 index 0000000000000..e89b6abcac33b --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant Y cannot be used as pattern + --> $DIR/cyclic-const-pattern-issue-144719.rs:11:12 + | +LL | if let Y = Y {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/drop-value-by-method.rs b/tests/ui/drop/drop-value-by-method.rs new file mode 100644 index 0000000000000..78c22d30e72b5 --- /dev/null +++ b/tests/ui/drop/drop-value-by-method.rs @@ -0,0 +1,31 @@ +//! Regression test for . +//! Initially a pretty-printer bug, which omitted parentheses around `move` +//! keyword in lhs (`(move z).f()`), now this behaviour is untestable as +//! plain `move` outside a closure doesn't exist. +//! +//! Now appears to test that drop works correctly when value is moved by method. +//@ run-pass + +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +struct thing { x: isize, } + +impl Drop for thing { + fn drop(&mut self) {} +} + +fn thing() -> thing { + thing { + x: 0 + } +} + +impl thing { + pub fn f(self) {} +} + +pub fn main() { + let z = thing(); + (z).f(); +} diff --git a/tests/ui/issues/issue-30380.rs b/tests/ui/drop/panic-in-drop-during-assignment.rs similarity index 77% rename from tests/ui/issues/issue-30380.rs rename to tests/ui/drop/panic-in-drop-during-assignment.rs index 49fce3d150cd7..d13bc022e7c8f 100644 --- a/tests/ui/issues/issue-30380.rs +++ b/tests/ui/drop/panic-in-drop-during-assignment.rs @@ -1,5 +1,6 @@ -// check that panics in destructors during assignment do not leave -// destroyed values lying around for other destructors to observe. +//! Regression test for . +//! Check that panics in destructors during assignment do not leave +//! destroyed values lying around for other destructors to observe. //@ run-fail //@ error-pattern:panicking destructors ftw! diff --git a/tests/ui/dst/unsized-tuple-trait-tail.rs b/tests/ui/dst/unsized-tuple-trait-tail.rs new file mode 100644 index 0000000000000..1fc66b8a866b9 --- /dev/null +++ b/tests/ui/dst/unsized-tuple-trait-tail.rs @@ -0,0 +1,15 @@ +//! Regression test for . +//! This used to fire LLVM assertion, and later on ICE because of +//! `t` type size incosistency between LLVM and rustc. +//@ check-pass + +use std::fmt; + +// CoerceUnsized is not implemented for tuples. You can still create +// an unsized tuple by transmuting a trait object. +fn any() -> T { unreachable!() } + +fn main() { + let t: &(u8, dyn fmt::Debug) = any(); + println!("{:?}", &t.1); +} diff --git a/tests/ui/issues/issue-3220.rs b/tests/ui/issues/issue-3220.rs deleted file mode 100644 index 2f5ca82b2fac3..0000000000000 --- a/tests/ui/issues/issue-3220.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -struct thing { x: isize, } - -impl Drop for thing { - fn drop(&mut self) {} -} - -fn thing() -> thing { - thing { - x: 0 - } -} - -impl thing { - pub fn f(self) {} -} - -pub fn main() { - let z = thing(); - (z).f(); -} diff --git a/tests/ui/issues/issue-30255.rs b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs similarity index 67% rename from tests/ui/issues/issue-30255.rs rename to tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs index 6970a122b7144..246082f54f08e 100644 --- a/tests/ui/issues/issue-30255.rs +++ b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs @@ -1,6 +1,6 @@ -// -// Test that lifetime elision error messages correctly omit parameters -// with no elided lifetimes +//! Regression test for . +//! Test that lifetime elision error messages correctly omit parameters +//! with no elided lifetimes. struct S<'a> { field: &'a i32, diff --git a/tests/ui/issues/issue-30255.stderr b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr similarity index 90% rename from tests/ui/issues/issue-30255.stderr rename to tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr index adb721a1cbaf1..fbabc9a56074b 100644 --- a/tests/ui/issues/issue-30255.stderr +++ b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:9:24 + --> $DIR/elision-error-omits-lifetimeless-params.rs:9:24 | LL | fn f(a: &S, b: i32) -> &i32 { | -- ^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | fn f<'a>(a: &'a S<'a>, b: i32) -> &'a i32 { | ++++ ++ ++++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:14:34 + --> $DIR/elision-error-omits-lifetimeless-params.rs:14:34 | LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { | -- ---- ^ expected named lifetime parameter @@ -23,7 +23,7 @@ LL | fn g<'a>(a: &'a S<'a>, b: bool, c: &'a i32) -> &'a i32 { | ++++ ++ ++++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:19:44 + --> $DIR/elision-error-omits-lifetimeless-params.rs:19:44 | LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { | ----- -- ---- ^ expected named lifetime parameter diff --git a/tests/ui/issues/issue-30371.rs b/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs similarity index 59% rename from tests/ui/issues/issue-30371.rs rename to tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs index d3ac5fd9587d1..6b266d7cc522c 100644 --- a/tests/ui/issues/issue-30371.rs +++ b/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to emit unused variable warning. //@ run-pass + #![allow(unreachable_code)] #![allow(for_loops_over_fallibles)] #![deny(unused_variables)] diff --git a/tests/ui/issues/issue-31011.rs b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs similarity index 83% rename from tests/ui/issues/issue-31011.rs rename to tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs index 078d8b2d50fc7..ed4a9a08c222c 100644 --- a/tests/ui/issues/issue-31011.rs +++ b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! This macro used to ICE with unprintable span. //@ dont-require-annotations: NOTE macro_rules! log { diff --git a/tests/ui/issues/issue-31011.stderr b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr similarity index 89% rename from tests/ui/issues/issue-31011.stderr rename to tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr index 701141ee4406c..600a569a84ce2 100644 --- a/tests/ui/issues/issue-31011.stderr +++ b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `trace` on type `&T` - --> $DIR/issue-31011.rs:5:17 + --> $DIR/no-field-error-in-macro-expansion-for-generic.rs:7:17 | LL | if $ctx.trace { | ^^^^^ unknown field diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs index a4660f4bf5734..1f3adede80465 100644 --- a/tests/ui/mir/null/borrowed_mut_null.rs +++ b/tests/ui/mir/null/borrowed_mut_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *mut u32 = std::ptr::null_mut(); diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs index 2a50058a48202..6857d2e64c660 100644 --- a/tests/ui/mir/null/borrowed_null.rs +++ b/tests/ui/mir/null/borrowed_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const u32 = std::ptr::null(); diff --git a/tests/ui/mir/null/borrowed_null_zst.rs b/tests/ui/mir/null/borrowed_null_zst.rs index 106fa00b1db5a..9a31f4c94f96a 100644 --- a/tests/ui/mir/null/borrowed_null_zst.rs +++ b/tests/ui/mir/null/borrowed_null_zst.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const () = std::ptr::null(); diff --git a/tests/ui/issues/issue-31776.rs b/tests/ui/privacy/required-pub-in-blocks.rs similarity index 86% rename from tests/ui/issues/issue-31776.rs rename to tests/ui/privacy/required-pub-in-blocks.rs index abe6c7ecee58e..aaf273641c917 100644 --- a/tests/ui/issues/issue-31776.rs +++ b/tests/ui/privacy/required-pub-in-blocks.rs @@ -1,8 +1,10 @@ +//! Regression test for . +//! Various scenarios in which `pub` is required in blocks. //@ run-pass + #![allow(dead_code)] #![allow(unused_variables)] #![allow(non_local_definitions)] -// Various scenarios in which `pub` is required in blocks struct S; diff --git a/tests/ui/issues/issue-3149.rs b/tests/ui/resolve/generic-struct-and-fn-share-name.rs similarity index 83% rename from tests/ui/issues/issue-3149.rs rename to tests/ui/resolve/generic-struct-and-fn-share-name.rs index 76744213d51da..7bcb64ffbc80d 100644 --- a/tests/ui/issues/issue-3149.rs +++ b/tests/ui/resolve/generic-struct-and-fn-share-name.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This wrongly emitted a duplicate definition of value error. //@ check-pass + #![allow(dead_code)] #![allow(non_snake_case)] diff --git a/tests/ui/issues/issue-30589.rs b/tests/ui/resolve/impl-trait-for-undeclared-type.rs similarity index 62% rename from tests/ui/issues/issue-30589.rs rename to tests/ui/resolve/impl-trait-for-undeclared-type.rs index 94eb5839958af..e023020cd71b6 100644 --- a/tests/ui/issues/issue-30589.rs +++ b/tests/ui/resolve/impl-trait-for-undeclared-type.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ICE when coherence encountered an erroneous type. + use std::fmt; impl fmt::Display for DecoderError { //~ ERROR cannot find type `DecoderError` in this scope diff --git a/tests/ui/issues/issue-30589.stderr b/tests/ui/resolve/impl-trait-for-undeclared-type.stderr similarity index 84% rename from tests/ui/issues/issue-30589.stderr rename to tests/ui/resolve/impl-trait-for-undeclared-type.stderr index 43d80896edf8c..72319af983dc6 100644 --- a/tests/ui/issues/issue-30589.stderr +++ b/tests/ui/resolve/impl-trait-for-undeclared-type.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `DecoderError` in this scope - --> $DIR/issue-30589.rs:3:23 + --> $DIR/impl-trait-for-undeclared-type.rs:6:23 | LL | impl fmt::Display for DecoderError { | ^^^^^^^^^^^^ not found in this scope diff --git a/tests/ui/issues/issue-3344.rs b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs similarity index 67% rename from tests/ui/issues/issue-3344.rs rename to tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs index de764b3d075d3..f4e0ced169972 100644 --- a/tests/ui/issues/issue-3344.rs +++ b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Unimplemented items in impl caused ICE. + #[derive(PartialEq)] struct Thing(usize); impl PartialOrd for Thing { //~ ERROR not all trait items implemented, missing: `partial_cmp` diff --git a/tests/ui/issues/issue-3344.stderr b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr similarity index 89% rename from tests/ui/issues/issue-3344.stderr rename to tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr index eac8f10fcc164..cae998c653397 100644 --- a/tests/ui/issues/issue-3344.stderr +++ b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `partial_cmp` - --> $DIR/issue-3344.rs:3:1 + --> $DIR/incomplete-partial-ord-impl.rs:6:1 | LL | impl PartialOrd for Thing { | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation diff --git a/tests/ui/traits/late-bound-type-method-probe.rs b/tests/ui/traits/late-bound-type-method-probe.rs new file mode 100644 index 0000000000000..ed6b3d866d7a2 --- /dev/null +++ b/tests/ui/traits/late-bound-type-method-probe.rs @@ -0,0 +1,19 @@ +// A method probe involving a late-bound type parameter should report normal +// diagnostics instead of ICEing while structurally normalizing obligations. + +#![feature(non_lifetime_binders)] +#![allow(incomplete_features)] + +pub trait T { + fn t(&self, _: F) {} + //~^ ERROR cannot find type `F` in this scope +} + +pub fn crash(v: &V) +where + for F: T + 'static, +{ + v.t(|| {}); +} + +fn main() {} diff --git a/tests/ui/traits/late-bound-type-method-probe.stderr b/tests/ui/traits/late-bound-type-method-probe.stderr new file mode 100644 index 0000000000000..0ddeb301d5e03 --- /dev/null +++ b/tests/ui/traits/late-bound-type-method-probe.stderr @@ -0,0 +1,17 @@ +error[E0425]: cannot find type `F` in this scope + --> $DIR/late-bound-type-method-probe.rs:8:26 + | +LL | fn t(&self, _: F) {} + | ^ + | + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here +help: a trait with a similar name exists + | +LL | fn t(&self, _: Fn) {} + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs new file mode 100644 index 0000000000000..89a37d8c75a31 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs @@ -0,0 +1,22 @@ +//! Regression test for +//@ compile-flags: -Znext-solver + +trait FooMut { + fn bar(&self, _: I) + where + for<'b> &'b I: Iterator; + + fn bar(&self, _: I) + //~^ ERROR: the name `bar` is defined multiple times + where + I: Iterator, + { + let collection = vec![_I].iter().map(|x| ()); + //~^ ERROR: cannot find value `_I` in this scope + self.bar(collection); + //~^ ERROR: `&'b _` is not an iterator + //~| ERROR: type mismatch resolving `<&_ as Iterator>::Item == &()` + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr new file mode 100644 index 0000000000000..0bd604d03fdf2 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr @@ -0,0 +1,71 @@ +error[E0428]: the name `bar` is defined multiple times + --> $DIR/iterator-item-suggest-no-ice.rs:9:5 + | +LL | / fn bar(&self, _: I) +LL | | where +LL | | for<'b> &'b I: Iterator; + | |_______________________________________________- previous definition of the value `bar` here +LL | +LL | / fn bar(&self, _: I) +LL | | +LL | | where +LL | | I: Iterator, +... | +LL | | } + | |_____^ `bar` redefined here + | + = note: `bar` must be defined only once in the value namespace of this trait + +error[E0425]: cannot find value `_I` in this scope + --> $DIR/iterator-item-suggest-no-ice.rs:14:31 + | +LL | let collection = vec![_I].iter().map(|x| ()); + | ^^ not found in this scope + +error[E0277]: `&'b _` is not an iterator + --> $DIR/iterator-item-suggest-no-ice.rs:16:18 + | +LL | self.bar(collection); + | --- ^^^^^^^^^^ `&'b _` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `for<'b> Iterator` is not implemented for `&'b _` +note: required by a bound in `FooMut::bar` + --> $DIR/iterator-item-suggest-no-ice.rs:7:24 + | +LL | fn bar(&self, _: I) + | --- required by a bound in this associated function +LL | where +LL | for<'b> &'b I: Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FooMut::bar` + +error[E0271]: type mismatch resolving `<&_ as Iterator>::Item == &()` + --> $DIR/iterator-item-suggest-no-ice.rs:16:18 + | +LL | self.bar(collection); + | --- ^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: the method call chain might not have had the expected associated types + --> $DIR/iterator-item-suggest-no-ice.rs:14:35 + | +LL | let collection = vec![_I].iter().map(|x| ()); + | -------- ^^^^^^ ----------- `Iterator::Item` remains `<{type error} as Iterator>::Item` here + | | | + | | `Iterator::Item` is `<{type error} as Iterator>::Item` here + | this expression has type `Vec<{type error}>` +note: required by a bound in `FooMut::bar` + --> $DIR/iterator-item-suggest-no-ice.rs:7:33 + | +LL | fn bar(&self, _: I) + | --- required by a bound in this associated function +LL | where +LL | for<'b> &'b I: Iterator; + | ^^^^^^^^^^^^^ required by this bound in `FooMut::bar` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0277, E0425, E0428. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs new file mode 100644 index 0000000000000..700e38cc3d8a2 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Znext-solver +//@ edition: 2024 + +// Previously, when building MIR body, we were using typing env +// `non_body_analysis` which is wrong since we're indeed in a body. +// It caused opaque types in defining body to be not revealed. +// This caused opaque types in the defining body not to be revealed. + +#![feature(type_alias_impl_trait)] + +struct Task(F); + +impl Task { + fn spawn(&self, _: impl FnOnce() -> Foo) {} +} +type Foo = impl Sized; + +#[define_opaque(Foo)] +fn foo() { + async fn cb() {} + Task::spawn(&POOL, cb) +} + +static POOL: Task = todo!(); +//~^ ERROR: evaluation panicked + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr new file mode 100644 index 0000000000000..95c000394a982 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: not yet implemented + --> $DIR/wrong-typing-mode-ice-1.rs:24:26 + | +LL | static POOL: Task = todo!(); + | ^^^^^^^ evaluation of `POOL` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs new file mode 100644 index 0000000000000..e27858b6b6fa0 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Previously, when building MIR body, we were using typing env +// `non_body_analysis` which is wrong since we're indeed in a body. +// It caused opaque types in defining body to be not revealed. +// This caused opaque types in the defining body not to be revealed. + +#![feature(type_alias_impl_trait)] +fn main() { + struct Foo(U); + type U = impl Copy; + let foo: _ = Foo(()); + let Foo(()) = foo; +} diff --git a/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs b/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs deleted file mode 100644 index e0c2ab5f303a3..0000000000000 --- a/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs +++ /dev/null @@ -1,14 +0,0 @@ -// https://github.com/rust-lang/rust/issues/32995 -fn main() { - { fn f() {} } - //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait - - { fn f() -> impl ::std::marker()::Send { } } - //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait -} - -#[derive(Clone)] -struct X; - -impl ::std::marker()::Copy for X {} -//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait diff --git a/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr b/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr deleted file mode 100644 index 590cdcdb43bc3..0000000000000 --- a/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:3:22 - | -LL | { fn f() {} } - | ^^^^^^^^ only `Fn` traits may use parentheses - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:6:29 - | -LL | { fn f() -> impl ::std::marker()::Send { } } - | ^^^^^^^^ only `Fn` traits may use parentheses - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:13:13 - | -LL | impl ::std::marker()::Copy for X {} - | ^^^^^^^^ only `Fn` traits may use parentheses - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/issues/issue-32995.rs b/tests/ui/typeck/parenthesized-type-params-in-paths.rs similarity index 62% rename from tests/ui/issues/issue-32995.rs rename to tests/ui/typeck/parenthesized-type-params-in-paths.rs index 0d07a76939f2a..85321cc305384 100644 --- a/tests/ui/issues/issue-32995.rs +++ b/tests/ui/typeck/parenthesized-type-params-in-paths.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test parenthesized type params syntax is forbidden for non `Fn` trait, +//! and can't be used in paths. + fn main() { let x: usize() = 1; //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait @@ -16,8 +20,21 @@ fn main() { let o : Box = Box::new(1); //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + { fn f() {} } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + { fn f() -> impl ::std::marker()::Send { } } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + } +#[derive(Clone)] +struct X; + +impl ::std::marker()::Copy for X {} +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + fn foo() { let d : X() = Default::default(); //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait diff --git a/tests/ui/issues/issue-32995.stderr b/tests/ui/typeck/parenthesized-type-params-in-paths.stderr similarity index 56% rename from tests/ui/issues/issue-32995.stderr rename to tests/ui/typeck/parenthesized-type-params-in-paths.stderr index b868011b99b24..7a8a4afbfd113 100644 --- a/tests/ui/issues/issue-32995.stderr +++ b/tests/ui/typeck/parenthesized-type-params-in-paths.stderr @@ -1,45 +1,63 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:2:12 + --> $DIR/parenthesized-type-params-in-paths.rs:6:12 | LL | let x: usize() = 1; | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:5:19 + --> $DIR/parenthesized-type-params-in-paths.rs:9:19 | LL | let b: ::std::boxed()::Box<_> = Box::new(1); | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:8:20 + --> $DIR/parenthesized-type-params-in-paths.rs:12:20 | LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:11:25 + --> $DIR/parenthesized-type-params-in-paths.rs:15:25 | LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); | ^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:14:29 + --> $DIR/parenthesized-type-params-in-paths.rs:18:29 | LL | let o : Box = Box::new(1); | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:17:35 + --> $DIR/parenthesized-type-params-in-paths.rs:21:35 | LL | let o : Box = Box::new(1); | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:22:13 + --> $DIR/parenthesized-type-params-in-paths.rs:24:22 + | +LL | { fn f() {} } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:27:29 + | +LL | { fn f() -> impl ::std::marker()::Send { } } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:35:13 + | +LL | impl ::std::marker()::Copy for X {} + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:39:13 | LL | let d : X() = Default::default(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0214`.