diff options
108 files changed, 1421 insertions, 392 deletions
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 67fdb671742..d8ca62565fa 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -166,6 +166,8 @@ borrowck_returned_lifetime_wrong = borrowck_returned_ref_escaped = returns a reference to a captured variable which escapes the closure body +borrowck_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item + borrowck_suggest_create_freash_reborrow = consider reborrowing the `Pin` instead of moving it diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index d1d8cfa74aa..ca3ccf439f2 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -452,3 +452,10 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[note(borrowck_ty_no_impl_copy)] Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } + +#[derive(Diagnostic)] +#[diag(borrowck_simd_shuffle_last_const)] +pub(crate) struct SimdShuffleLastConst { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 28286243e82..0f661421cdc 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -50,7 +50,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; -use crate::session_diagnostics::MoveUnsized; +use crate::session_diagnostics::{MoveUnsized, SimdShuffleLastConst}; use crate::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, @@ -1426,7 +1426,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .add_element(region_vid, term_location); } - self.check_call_inputs(body, term, &sig, args, term_location, *call_source); + self.check_call_inputs(body, term, func, &sig, args, term_location, *call_source); } TerminatorKind::Assert { cond, msg, .. } => { self.check_operand(cond, term_location); @@ -1546,25 +1546,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self, body, term, func, term_location, call_source))] fn check_call_inputs( &mut self, body: &Body<'tcx>, term: &Terminator<'tcx>, + func: &Operand<'tcx>, sig: &ty::FnSig<'tcx>, args: &[Operand<'tcx>], term_location: Location, call_source: CallSource, ) { - debug!("check_call_inputs({:?}, {:?})", sig, args); if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind { - Some(func.ty(body, self.infcx.tcx)) - } else { - None - }; + let func_ty = func.ty(body, self.infcx.tcx); + if let ty::FnDef(def_id, _) = *func_ty.kind() { + if self.tcx().is_intrinsic(def_id) { + match self.tcx().item_name(def_id) { + sym::simd_shuffle => { + if !matches!(args[2], Operand::Constant(_)) { + self.tcx() + .sess + .emit_err(SimdShuffleLastConst { span: term.source_info.span }); + } + } + _ => {} + } + } + } debug!(?func_ty); for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { @@ -1572,7 +1583,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let op_arg_ty = self.normalize(op_arg_ty, term_location); let category = if call_source.from_hir_call() { - ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty)) + ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty))) } else { ConstraintCategory::Boring }; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 47cc5bd52e2..c49d322fc00 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -216,6 +216,24 @@ pub fn target_machine_factory( let force_emulated_tls = sess.target.force_emulated_tls; + // copy the exe path, followed by path all into one buffer + // null terminating them so we can use them as null terminated strings + let args_cstr_buff = { + let mut args_cstr_buff: Vec<u8> = Vec::new(); + let exe_path = std::env::current_exe().unwrap_or_default(); + let exe_path_str = exe_path.into_os_string().into_string().unwrap_or_default(); + + args_cstr_buff.extend_from_slice(exe_path_str.as_bytes()); + args_cstr_buff.push(0); + + for arg in sess.expanded_args.iter() { + args_cstr_buff.extend_from_slice(arg.as_bytes()); + args_cstr_buff.push(0); + } + + args_cstr_buff + }; + Arc::new(move |config: TargetMachineFactoryConfig| { let split_dwarf_file = path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; @@ -242,6 +260,8 @@ pub fn target_machine_factory( use_init_array, split_dwarf_file.as_ptr(), force_emulated_tls, + args_cstr_buff.as_ptr() as *const c_char, + args_cstr_buff.len(), ) }; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 01cbf7d3b11..1f03c932cfd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2132,7 +2132,10 @@ extern "C" { UseInitArray: bool, SplitDwarfFile: *const c_char, ForceEmulatedTls: bool, + ArgsCstrBuff: *const c_char, + ArgsCstrBuffLen: usize, ) -> Option<&'static mut TargetMachine>; + pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index f485af00bca..3bf98c46dea 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -343,6 +343,12 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, + /// All commandline args used to invoke the compiler, with @file args fully expanded. + /// This will only be used within debug info, e.g. in the pdb file on windows + /// This is mainly useful for other tools that reads that debuginfo to figure out + /// how to call the compiler with the same arguments. + pub expanded_args: Vec<String>, + /// Handler to use for diagnostics produced during codegen. pub diag_emitter: SharedEmitter, /// LLVM optimizations for which we want to print remarks. @@ -1108,6 +1114,7 @@ fn start_executing_work<B: ExtraBackendMethods>( incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(), coordinator_send, + expanded_args: tcx.sess.expanded_args.clone(), diag_emitter: shared_emitter.clone(), output_filenames: tcx.output_filenames(()).clone(), regular_module_config: regular_config, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d8ad82d3da0..90f2b470179 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -796,6 +796,13 @@ where dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, ) -> InterpResult<'tcx> { + // Generally for transmutation, data must be valid both at the old and new type. + // But if the types are the same, the 2nd validation below suffices. + if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) { + self.validate_operand(&src.to_op(self)?)?; + } + + // Do the actual copy. self.copy_op_no_validate(src, dest, allow_transmute)?; if M::enforce_validity(self, dest.layout()) { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1a16759d7f9..e56347ab38e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -313,6 +313,7 @@ fn run_compiler( override_queries: None, make_codegen_backend, registry: diagnostics_registry(), + expanded_args: args, }; match make_input(&early_error_handler, &matches.free) { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aaabf1482e2..dabebe0adc0 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -764,13 +764,13 @@ impl<'tcx> InferCtxt<'tcx> { .collect(); vars.extend( (0..inner.int_unification_table().len()) - .map(|i| ty::IntVid { index: i as u32 }) + .map(|i| ty::IntVid::from_u32(i as u32)) .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none()) .map(|v| Ty::new_int_var(self.tcx, v)), ); vars.extend( (0..inner.float_unification_table().len()) - .map(|i| ty::FloatVid { index: i as u32 }) + .map(|i| ty::FloatVid::from_u32(i as u32)) .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none()) .map(|v| Ty::new_float_var(self.tcx, v)), ); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5b417e008cf..a0f0b530bae 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -279,6 +279,12 @@ pub struct Config { /// Registry of diagnostics codes. pub registry: Registry, + + /// All commandline args used to invoke the compiler, with @file args fully expanded. + /// This will only be used within debug info, e.g. in the pdb file on windows + /// This is mainly useful for other tools that reads that debuginfo to figure out + /// how to call the compiler with the same arguments. + pub expanded_args: Vec<String>, } // JUSTIFICATION: before session exists, only config @@ -317,6 +323,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.make_codegen_backend, registry.clone(), config.ice_file, + config.expanded_args, ); if let Some(parse_sess_created) = config.parse_sess_created { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b53ba251bcd..ccf8b5630d4 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -68,6 +68,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se None, "", None, + Default::default(), ); (sess, cfg) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 5c9b39cdbe3..37e242c6e40 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -71,6 +71,7 @@ pub fn create_session( >, descriptions: Registry, ice_file: Option<PathBuf>, + expanded_args: Vec<String>, ) -> (Session, Box<dyn CodegenBackend>) { let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) @@ -113,6 +114,7 @@ pub fn create_session( target_override, rustc_version_str().unwrap_or("unknown"), ice_file, + expanded_args, ); codegen_backend.init(&sess); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 194ebe6d968..5ecf3aec65d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -409,7 +409,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool RelaxELFRelocations, bool UseInitArray, const char *SplitDwarfFile, - bool ForceEmulatedTls) { + bool ForceEmulatedTls, + const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { auto OptLevel = fromRust(RustOptLevel); auto RM = fromRust(RustReloc); @@ -465,12 +466,48 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.EmitStackSizeSection = EmitStackSizeSection; + + if (ArgsCstrBuff != nullptr) + { + int buffer_offset = 0; + assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0'); + + const size_t arg0_len = std::strlen(ArgsCstrBuff); + char* arg0 = new char[arg0_len + 1]; + memcpy(arg0, ArgsCstrBuff, arg0_len); + arg0[arg0_len] = '\0'; + buffer_offset += arg0_len + 1; + + const int num_cmd_arg_strings = + std::count(&ArgsCstrBuff[buffer_offset], &ArgsCstrBuff[ArgsCstrBuffLen], '\0'); + + std::string* cmd_arg_strings = new std::string[num_cmd_arg_strings]; + for (int i = 0; i < num_cmd_arg_strings; ++i) + { + assert(buffer_offset < ArgsCstrBuffLen); + const int len = std::strlen(ArgsCstrBuff + buffer_offset); + cmd_arg_strings[i] = std::string(&ArgsCstrBuff[buffer_offset], len); + buffer_offset += len + 1; + } + + assert(buffer_offset == ArgsCstrBuffLen); + + Options.MCOptions.Argv0 = arg0; + Options.MCOptions.CommandLineArgs = + llvm::ArrayRef<std::string>(cmd_arg_strings, num_cmd_arg_strings); + } + TargetMachine *TM = TheTarget->createTargetMachine( Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel); return wrap(TM); } extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { + + MCTargetOptions& MCOptions = unwrap(TM)->Options.MCOptions; + delete[] MCOptions.Argv0; + delete[] MCOptions.CommandLineArgs.data(); + delete unwrap(TM); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ac0c88468fa..12254ed1a4d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1123,6 +1123,17 @@ pub trait PrettyPrinter<'tcx>: } } + if self.tcx().features().return_type_notation + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = self.tcx().opt_rpitit_info(def_id) + && let ty::Alias(_, alias_ty) = self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() + && alias_ty.def_id == def_id + { + let num_args = self.tcx().generics_of(fn_def_id).count(); + write!(self, " {{ ")?; + self = self.print_def_path(fn_def_id, &args[..num_args])?; + write!(self, "() }}")?; + } + Ok(self) } @@ -1239,21 +1250,18 @@ pub trait PrettyPrinter<'tcx>: .generics_of(principal.def_id) .own_args_no_defaults(cx.tcx(), principal.args); - let mut projections = predicates.projection_bounds(); - - let mut args = args.iter().cloned(); - let arg0 = args.next(); - let projection0 = projections.next(); - if arg0.is_some() || projection0.is_some() { - let args = arg0.into_iter().chain(args); - let projections = projection0.into_iter().chain(projections); + let mut projections: Vec<_> = predicates.projection_bounds().collect(); + projections.sort_by_cached_key(|proj| { + cx.tcx().item_name(proj.item_def_id()).to_string() + }); + if !args.is_empty() || !projections.is_empty() { p!(generic_delimiters(|mut cx| { - cx = cx.comma_sep(args)?; - if arg0.is_some() && projection0.is_some() { + cx = cx.comma_sep(args.iter().copied())?; + if !args.is_empty() && !projections.is_empty() { write!(cx, ", ")?; } - cx.comma_sep(projections) + cx.comma_sep(projections.iter().copied()) })); } } diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index 2598eb2ed09..5a99afc45b0 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -42,8 +42,6 @@ mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in } .not_inherited = items do not inherit unsafety from separate enclosing items -mir_transform_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item - mir_transform_target_feature_call_label = call to function with `#[target_feature]` mir_transform_target_feature_call_note = can only be called if the required target features are available diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index aa205655f9d..56365c5d474 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,5 +1,6 @@ use super::*; +use rustc_data_structures::captures::Captures; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; use rustc_middle::query::Providers; @@ -12,15 +13,10 @@ pub(crate) fn provide(providers: &mut Providers) { providers.covered_code_regions = |tcx, def_id| covered_code_regions(tcx, def_id); } -/// The `num_counters` argument to `llvm.instrprof.increment` is the max counter_id + 1, or in -/// other words, the number of counter value references injected into the MIR (plus 1 for the -/// reserved `ZERO` counter, which uses counter ID `0` when included in an expression). Injected -/// counters have a counter ID from `1..num_counters-1`. -/// -/// `num_expressions` is the number of counter expressions added to the MIR body. -/// -/// Both `num_counters` and `num_expressions` are used to initialize new vectors, during backend -/// code generate, to lookup counters and expressions by simple u32 indexes. +/// Coverage codegen needs to know the total number of counter IDs and expression IDs that have +/// been used by a function's coverage mappings. These totals are used to create vectors to hold +/// the relevant counter and expression data, and the maximum counter ID (+ 1) is also needed by +/// the `llvm.instrprof.increment` intrinsic. /// /// MIR optimization may split and duplicate some BasicBlock sequences, or optimize out some code /// including injected counters. (It is OK if some counters are optimized out, but those counters @@ -28,71 +24,51 @@ pub(crate) fn provide(providers: &mut Providers) { /// calls may not work; but computing the number of counters or expressions by adding `1` to the /// highest ID (for a given instrumented function) is valid. /// -/// This visitor runs twice, first with `add_missing_operands` set to `false`, to find the maximum -/// counter ID and maximum expression ID based on their enum variant `id` fields; then, as a -/// safeguard, with `add_missing_operands` set to `true`, to find any other counter or expression -/// IDs referenced by expression operands, if not already seen. -/// -/// Ideally, each operand ID in a MIR `CoverageKind::Expression` will have a separate MIR `Coverage` -/// statement for the `Counter` or `Expression` with the referenced ID. but since current or future -/// MIR optimizations can theoretically optimize out segments of a MIR, it may not be possible to -/// guarantee this, so the second pass ensures the `CoverageInfo` counts include all referenced IDs. +/// It's possible for a coverage expression to remain in MIR while one or both of its operands +/// have been optimized away. To avoid problems in codegen, we include those operands' IDs when +/// determining the maximum counter/expression ID, even if the underlying counter/expression is +/// no longer present. struct CoverageVisitor { - info: CoverageInfo, - add_missing_operands: bool, + max_counter_id: CounterId, + max_expression_id: ExpressionId, } impl CoverageVisitor { - /// Updates `num_counters` to the maximum encountered counter ID plus 1. + /// Updates `max_counter_id` to the maximum encountered counter ID. #[inline(always)] - fn update_num_counters(&mut self, counter_id: CounterId) { - let counter_id = counter_id.as_u32(); - self.info.num_counters = std::cmp::max(self.info.num_counters, counter_id + 1); + fn update_max_counter_id(&mut self, counter_id: CounterId) { + self.max_counter_id = self.max_counter_id.max(counter_id); } - /// Updates `num_expressions` to the maximum encountered expression ID plus 1. + /// Updates `max_expression_id` to the maximum encountered expression ID. #[inline(always)] - fn update_num_expressions(&mut self, expression_id: ExpressionId) { - let expression_id = expression_id.as_u32(); - self.info.num_expressions = std::cmp::max(self.info.num_expressions, expression_id + 1); + fn update_max_expression_id(&mut self, expression_id: ExpressionId) { + self.max_expression_id = self.max_expression_id.max(expression_id); } fn update_from_expression_operand(&mut self, operand: Operand) { match operand { - Operand::Counter(id) => self.update_num_counters(id), - Operand::Expression(id) => self.update_num_expressions(id), + Operand::Counter(id) => self.update_max_counter_id(id), + Operand::Expression(id) => self.update_max_expression_id(id), Operand::Zero => {} } } fn visit_body(&mut self, body: &Body<'_>) { - for bb_data in body.basic_blocks.iter() { - for statement in bb_data.statements.iter() { - if let StatementKind::Coverage(box ref coverage) = statement.kind { - if is_inlined(body, statement) { - continue; - } - self.visit_coverage(coverage); - } - } + for coverage in all_coverage_in_mir_body(body) { + self.visit_coverage(coverage); } } fn visit_coverage(&mut self, coverage: &Coverage) { - if self.add_missing_operands { - match coverage.kind { - CoverageKind::Expression { lhs, rhs, .. } => { - self.update_from_expression_operand(lhs); - self.update_from_expression_operand(rhs); - } - _ => {} - } - } else { - match coverage.kind { - CoverageKind::Counter { id, .. } => self.update_num_counters(id), - CoverageKind::Expression { id, .. } => self.update_num_expressions(id), - _ => {} + match coverage.kind { + CoverageKind::Counter { id, .. } => self.update_max_counter_id(id), + CoverageKind::Expression { id, lhs, rhs, .. } => { + self.update_max_expression_id(id); + self.update_from_expression_operand(lhs); + self.update_from_expression_operand(rhs); } + CoverageKind::Unreachable => {} } } } @@ -101,37 +77,40 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> let mir_body = tcx.instance_mir(instance_def); let mut coverage_visitor = CoverageVisitor { - info: CoverageInfo { num_counters: 0, num_expressions: 0 }, - add_missing_operands: false, + max_counter_id: CounterId::START, + max_expression_id: ExpressionId::START, }; coverage_visitor.visit_body(mir_body); - coverage_visitor.add_missing_operands = true; - coverage_visitor.visit_body(mir_body); - - coverage_visitor.info + // Add 1 to the highest IDs to get the total number of IDs. + CoverageInfo { + num_counters: (coverage_visitor.max_counter_id + 1).as_u32(), + num_expressions: (coverage_visitor.max_expression_id + 1).as_u32(), + } } fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> { let body = mir_body(tcx, def_id); - body.basic_blocks - .iter() - .flat_map(|data| { - data.statements.iter().filter_map(|statement| match statement.kind { - StatementKind::Coverage(box ref coverage) => { - if is_inlined(body, statement) { - None - } else { - coverage.code_region.as_ref() // may be None - } - } - _ => None, - }) - }) + all_coverage_in_mir_body(body) + // Not all coverage statements have an attached code region. + .filter_map(|coverage| coverage.code_region.as_ref()) .collect() } +fn all_coverage_in_mir_body<'a, 'tcx>( + body: &'a Body<'tcx>, +) -> impl Iterator<Item = &'a Coverage> + Captures<'tcx> { + body.basic_blocks.iter().flat_map(|bb_data| &bb_data.statements).filter_map(|statement| { + match statement.kind { + StatementKind::Coverage(box ref coverage) if !is_inlined(body, statement) => { + Some(coverage) + } + _ => None, + } + }) +} + fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { let scope_data = &body.source_scopes[statement.source_info.scope]; scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 4b796d79ef6..35373bcaa41 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -258,10 +258,3 @@ pub(crate) struct MustNotSuspendReason { pub span: Span, pub reason: String, } - -#[derive(Diagnostic)] -#[diag(mir_transform_simd_shuffle_last_const)] -pub(crate) struct SimdShuffleLastConst { - #[primary_span] - pub span: Span, -} diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index a8dc91ca439..13277d62bf4 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -1,11 +1,10 @@ //! Lowers intrinsic calls -use crate::{errors, MirPass}; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx}; pub struct LowerIntrinsics; @@ -304,9 +303,6 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Unreachable; } } - sym::simd_shuffle => { - validate_simd_shuffle(tcx, args, terminator.source_info.span); - } _ => {} } } @@ -325,9 +321,3 @@ fn resolve_rust_intrinsic<'tcx>( } None } - -fn validate_simd_shuffle<'tcx>(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { - if !matches!(args[2], Operand::Constant(_)) { - tcx.sess.emit_err(errors::SimdShuffleLastConst { span }); - } -} diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 906a36cdb25..aedc7b22725 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1463,14 +1463,15 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let vis = self.tcx.local_visibility(local_def_id); - let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); let span = self.tcx.def_span(self.item_def_id.to_def_id()); let vis_span = self.tcx.def_span(def_id); if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) { let vis_descr = match vis { ty::Visibility::Public => "public", ty::Visibility::Restricted(vis_def_id) => { - if vis_def_id == self.tcx.parent_module(hir_id).to_local_def_id() { + if vis_def_id + == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id() + { "private" } else if vis_def_id.is_top_level_module() { "crate-private" @@ -1504,7 +1505,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; self.tcx.emit_spanned_lint( lint, - hir_id, + self.tcx.hir().local_def_id_to_hir_id(self.item_def_id), span, PrivateInterfacesOrBoundsLint { item_span: span, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f00472f181d..302e4e55d59 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2160,12 +2160,6 @@ fn collect_print_requests( prints.extend(matches.opt_strs("print").into_iter().map(|req| { let (req, out) = split_out_file_name(&req); - if out.is_some() && !unstable_opts.unstable_options { - handler.early_error( - "the `-Z unstable-options` flag must also be passed to \ - enable the path print option", - ); - } let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) { Some((_, PrintKind::TargetSpec)) => { if unstable_opts.unstable_options { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 86db2edab7b..9bff9017881 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -204,6 +204,12 @@ pub struct Session { /// The version of the rustc process, possibly including a commit hash and description. pub cfg_version: &'static str, + + /// All commandline args used to invoke the compiler, with @file args fully expanded. + /// This will only be used within debug info, e.g. in the pdb file on windows + /// This is mainly useful for other tools that reads that debuginfo to figure out + /// how to call the compiler with the same arguments. + pub expanded_args: Vec<String>, } pub struct PerfStats { @@ -1325,6 +1331,7 @@ pub fn build_session( target_override: Option<Target>, cfg_version: &'static str, ice_file: Option<PathBuf>, + expanded_args: Vec<String>, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -1467,6 +1474,7 @@ pub fn build_session( target_features: Default::default(), unstable_target_features: Default::default(), cfg_version, + expanded_args, }; validate_commandline_args_with_session_available(&sess); 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 611ec6b00ef..32fb10ce4a6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -838,7 +838,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation.param_env, real_trait_pred_and_base_ty, ); - if self.predicate_may_hold(&obligation) { + let sized_obligation = Obligation::new( + self.tcx, + obligation.cause.clone(), + obligation.param_env, + ty::TraitRef::from_lang_item( + self.tcx, + hir::LangItem::Sized, + obligation.cause.span, + [base_ty], + ), + ); + if self.predicate_may_hold(&obligation) + && self.predicate_must_hold_modulo_regions(&sized_obligation) + { let call_node = self.tcx.hir().get(*call_hir_id); let msg = "consider dereferencing here"; let is_receiver = matches!( diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 34fd31e49e1..1fc5d9359a4 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -19,13 +19,32 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> // needs drop. let adt_has_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = - drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some(); + let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) + .filter(filter_array_elements(tcx, query.param_env)) + .next() + .is_some(); debug!("needs_drop_raw({:?}) = {:?}", query, res); res } +/// HACK: in order to not mistakenly assume that `[PhantomData<T>; N]` requires drop glue +/// we check the element type for drop glue. The correct fix would be looking at the +/// entirety of the code around `needs_drop_components` and this file and come up with +/// logic that is easier to follow while not repeating any checks that may thus diverge. +fn filter_array_elements<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> impl Fn(&Result<Ty<'tcx>, AlwaysRequiresDrop>) -> bool { + move |ty| match ty { + Ok(ty) => match *ty.kind() { + ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)), + _ => true, + }, + Err(AlwaysRequiresDrop) => true, + } +} + fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -37,6 +56,7 @@ fn has_significant_drop_raw<'tcx>( adt_consider_insignificant_dtor(tcx), true, ) + .filter(filter_array_elements(tcx, query.param_env)) .next() .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e0abc7f04f5..e348591ebba 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -574,16 +574,16 @@ rustc_index::newtype_index! { pub struct TyVid {} } -/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct IntVid { - pub index: u32, +rustc_index::newtype_index! { + /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. + #[debug_format = "?{}i"] + pub struct IntVid {} } -/// An **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct FloatVid { - pub index: u32, +rustc_index::newtype_index! { + /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. + #[debug_format = "?{}f"] + pub struct FloatVid {} } /// A placeholder for a type that hasn't been inferred yet. @@ -645,11 +645,11 @@ impl UnifyKey for IntVid { type Value = Option<IntVarValue>; #[inline] // make this function eligible for inlining - it is quite hot. fn index(&self) -> u32 { - self.index + self.as_u32() } #[inline] fn from_index(i: u32) -> IntVid { - IntVid { index: i } + IntVid::from_u32(i) } fn tag() -> &'static str { "IntVid" @@ -662,11 +662,11 @@ impl UnifyKey for FloatVid { type Value = Option<FloatVarValue>; #[inline] fn index(&self) -> u32 { - self.index + self.as_u32() } #[inline] fn from_index(i: u32) -> FloatVid { - FloatVid { index: i } + FloatVid::from_u32(i) } fn tag() -> &'static str { "FloatVid" @@ -770,18 +770,6 @@ impl fmt::Debug for FloatVarValue { } } -impl fmt::Debug for IntVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "?{}i", self.index) - } -} - -impl fmt::Debug for FloatVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "?{}f", self.index) - } -} - impl fmt::Debug for Variance { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 515b8d20ead..4ac956e7b76 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -9,8 +9,58 @@ use crate::unicode::{self, conversions}; use super::*; impl char { + /// The lowest valid code point a `char` can have, `'\0'`. + /// + /// Unlike integer types, `char` actually has a gap in the middle, + /// meaning that the range of possible `char`s is smaller than you + /// might expect. Ranges of `char` will automatically hop this gap + /// for you: + /// + /// ``` + /// #![feature(char_min)] + /// let dist = u32::from(char::MAX) - u32::from(char::MIN); + /// let size = (char::MIN..=char::MAX).count() as u32; + /// assert!(size < dist); + /// ``` + /// + /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for + /// all `char` values. + /// + /// [`MAX`]: char::MAX + /// + /// # Examples + /// + /// ``` + /// #![feature(char_min)] + /// # fn something_which_returns_char() -> char { 'a' } + /// let c: char = something_which_returns_char(); + /// assert!(char::MIN <= c); + /// + /// let value_at_min = u32::from(char::MIN); + /// assert_eq!(char::from_u32(value_at_min), Some('\0')); + /// ``` + #[unstable(feature = "char_min", issue = "114298")] + pub const MIN: char = '\0'; + /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. /// + /// Unlike integer types, `char` actually has a gap in the middle, + /// meaning that the range of possible `char`s is smaller than you + /// might expect. Ranges of `char` will automatically hop this gap + /// for you: + /// + /// ``` + /// #![feature(char_min)] + /// let dist = u32::from(char::MAX) - u32::from(char::MIN); + /// let size = (char::MIN..=char::MAX).count() as u32; + /// assert!(size < dist); + /// ``` + /// + /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for + /// all `char` values. + /// + /// [`MIN`]: char::MIN + /// /// # Examples /// /// ``` @@ -18,7 +68,7 @@ impl char { /// let c: char = something_which_returns_char(); /// assert!(c <= char::MAX); /// - /// let value_at_max = char::MAX as u32; + /// let value_at_max = u32::from(char::MAX); /// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}')); /// assert_eq!(char::from_u32(value_at_max + 1), None); /// ``` diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 732fcce0f29..bc701d97bbb 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1126,6 +1126,11 @@ impl<T> fmt::Debug for Discriminant<T> { /// /// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations /// +/// The value of a [`Discriminant<T>`] is independent of any *lifetimes* in `T`. As such, reading +/// or writing a `Discriminant<Foo<'a>>` as a `Discriminant<Foo<'b>>` (whether via [`transmute`] or +/// otherwise) is always sound. Note that this is **not** true for other kinds of generic +/// parameters; `Discriminant<Foo<A>>` and `Discriminant<Foo<B>>` might be incompatible. +/// /// # Examples /// /// This can be used to compare enums that carry data, while disregarding diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 9dbb3f9d322..6d623b82c1c 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -109,7 +109,7 @@ impl<T: ?Sized> *mut T { /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit /// coercion. /// - /// [`cast_mut`]: #method.cast_mut + /// [`cast_mut`]: pointer::cast_mut #[stable(feature = "ptr_const_cast", since = "1.65.0")] #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] #[rustc_diagnostic_item = "ptr_cast_const"] @@ -121,7 +121,7 @@ impl<T: ?Sized> *mut T { /// Casts a pointer to its raw bits. /// /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`from_bits`](#method.from_bits-1). + /// The inverse method is [`from_bits`](pointer#method.from_bits-1). /// /// In particular, `*p as usize` and `p as usize` will both compile for /// pointers to numeric types but do very different things, so using this @@ -157,7 +157,7 @@ impl<T: ?Sized> *mut T { /// Creates a pointer from its raw bits. /// /// This is equivalent to `as *mut T`, but is more specific to enhance readability. - /// The inverse method is [`to_bits`](#method.to_bits-1). + /// The inverse method is [`to_bits`](pointer#method.to_bits-1). /// /// # Examples /// @@ -307,7 +307,7 @@ impl<T: ?Sized> *mut T { /// /// For the mutable counterpart see [`as_mut`]. /// - /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 /// [`as_mut`]: #method.as_mut /// /// # Safety @@ -373,7 +373,7 @@ impl<T: ?Sized> *mut T { /// /// For the mutable counterpart see [`as_uninit_mut`]. /// - /// [`as_ref`]: #method.as_ref-1 + /// [`as_ref`]: pointer#method.as_ref-1 /// [`as_uninit_mut`]: #method.as_uninit_mut /// /// # Safety @@ -628,7 +628,7 @@ impl<T: ?Sized> *mut T { /// For the shared counterpart see [`as_ref`]. /// /// [`as_uninit_mut`]: #method.as_uninit_mut - /// [`as_ref`]: #method.as_ref-1 + /// [`as_ref`]: pointer#method.as_ref-1 /// /// # Safety /// @@ -693,7 +693,7 @@ impl<T: ?Sized> *mut T { /// For the shared counterpart see [`as_uninit_ref`]. /// /// [`as_mut`]: #method.as_mut - /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 /// /// # Safety /// @@ -783,7 +783,7 @@ impl<T: ?Sized> *mut T { /// /// This function is the inverse of [`offset`]. /// - /// [`offset`]: #method.offset-1 + /// [`offset`]: pointer#method.offset-1 /// /// # Safety /// @@ -2064,7 +2064,7 @@ impl<T> *mut [T] { /// /// For the mutable counterpart see [`as_uninit_slice_mut`]. /// - /// [`as_ref`]: #method.as_ref-1 + /// [`as_ref`]: pointer#method.as_ref-1 /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut /// /// # Safety diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index a24a6a4636d..c62548875bf 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -302,8 +302,10 @@ impl StepDescription { } } - fn maybe_run(&self, builder: &Builder<'_>, pathsets: Vec<PathSet>) { - if pathsets.iter().any(|set| self.is_excluded(builder, set)) { + fn maybe_run(&self, builder: &Builder<'_>, mut pathsets: Vec<PathSet>) { + pathsets.retain(|set| !self.is_excluded(builder, set)); + + if pathsets.is_empty() { return; } diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 43b4a34fe5b..80e66622e8b 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -136,9 +136,9 @@ fn test_exclude_kind() { let mut config = configure("test", &["A"], &["A"]); // Ensure our test is valid, and `test::Rustc` would be run without the exclude. assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>()); - // Ensure tests for rustc are skipped. + // Ensure tests for rustc are not skipped. config.skip = vec![path.clone()]; - assert!(!run_build(&[], config.clone()).contains::<test::CrateLibrustc>()); + assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>()); // Ensure builds for rustc are not skipped. assert!(run_build(&[], config).contains::<compile::Rustc>()); } diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh index 7dae90f4403..689fe52863e 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 7018e24d8fe248596819d2e884761676f3542a04 +git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index 45174e708dc..4b0d360686f 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 7018e24d8fe248596819d2e884761676f3542a04 +git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile index 02b4664eb55..0d0f1edd003 100644 --- a/src/ci/docker/host-x86_64/wasm32/Dockerfile +++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile @@ -58,5 +58,6 @@ ENV NO_CHANGE_USER=1 RUN chown 10719 -R /emsdk-portable/ # Exclude library/alloc due to OOM in benches. +# FIXME: Fix std tests ENV SCRIPT python3 ../x.py test --stage 2 --host='' --target $TARGETS \ - --skip library/alloc + --skip library/alloc --skip library/std diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 2c7c05c0c4b..4d32897cc14 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -260,6 +260,10 @@ The valid types of print values are: This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable is present in the environment, or otherwise returns the variable's parsed value. +A filepath may optionally be specified for each requested information kind, in +the format `--print KIND=PATH`, just like for `--emit`. When a path is +specified, information will be written there instead of to stdout. + [conditional compilation]: ../reference/conditional-compilation.html [deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 2cb0a8f3c17..269fe928754 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -181,6 +181,7 @@ target | std | notes `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI +[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` @@ -323,7 +324,6 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL -[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md index b3eb34de638..23b99924899 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md @@ -1,6 +1,6 @@ # `wasm32-wasi-preview1-threads` -**Tier: 3** +**Tier: 2** The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an experimental target. This target is an extension to `wasm32-wasi-preview1` target, @@ -70,12 +70,6 @@ compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can reliably interoperate with C code in this mode (yet). -This target is not a stable target. This means that there are not many engines -which implement the `wasi-threads` feature and if they do they're likely behind a -flag, for example: - -* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads` - Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the presence of other merged wasm proposals such as (with their LLVM feature flags): @@ -94,6 +88,17 @@ The target intends to match the corresponding Clang target for its `"C"` ABI. > found it's recommended to open an issue either with rust-lang/rust or ideally > with LLVM itself. +## Platform requirements + +The runtime should support the same set of APIs as any other supported wasi target for interacting with the host environment through the WASI standard. The runtime also should have implemetation of [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads). + +This target is not a stable target. This means that there are a few engines +which implement the `wasi-threads` feature and if they do they're likely behind a +flag, for example: + +* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads` +* [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) - needs to be built with WAMR_BUILD_LIB_WASI_THREADS=1 + ## Building the target Users need to install or built wasi-sdk since release 20.0 @@ -110,12 +115,16 @@ After that users can build this by adding it to the `target` list in ## Building Rust programs -Since it is Tier 3, rust doesn't ship pre-compiled artifacts for this target. +From Rust Nightly 1.71.1 (2023-08-03) on the artifacts are shipped pre-compiled: + +```text +rustup target add wasm32-wasi-preview1-threads --toolchain nightly +``` + +Rust programs can be built for that target: -Specify `wasi-root` as explained in the previous section and then use the `build-std` -nightly cargo feature to build the standard library: -```shell -cargo +nightly build --target=wasm32-wasi-preview1-threads -Zbuild-std +```text +rustc --target wasm32-wasi-preview1-threads your-code.rs ``` ## Cross-compilation diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 9deb7009cfe..cd6e29ffd66 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -38,6 +38,22 @@ followed by a list of fields or variants for Rust types. Finally, the page lists associated functions and trait implementations, including automatic and blanket implementations that `rustdoc` knows about. +### Sections + +<!-- FIXME: Implementations --> +<!-- FIXME: Trait Implementations --> +<!-- FIXME: Implementors --> +<!-- FIXME: Auto Trait Implementations --> + +#### Aliased Type + +A type alias is expanded at compile time to its +[aliased type](https://doc.rust-lang.org/reference/items/type-aliases.html). +That may involve substituting some or all of the type parameters in the target +type with types provided by the type alias definition. The Aliased Type section +shows the result of this expansion, including the types of public fields or +variants, which may depend on those substitutions. + ### Navigation Subheadings, variants, fields, and many other things in this documentation diff --git a/src/doc/unstable-book/src/compiler-flags/path-options.md b/src/doc/unstable-book/src/compiler-flags/path-options.md deleted file mode 100644 index 0786ef1f166..00000000000 --- a/src/doc/unstable-book/src/compiler-flags/path-options.md +++ /dev/null @@ -1,11 +0,0 @@ -# `--print` Options - -The behavior of the `--print` flag can be modified by optionally be specifying a filepath -for each requested information kind, in the format `--print KIND=PATH`, just like for -`--emit`. When a path is specified, information will be written there instead of to stdout. - -This is unstable feature, so you have to provide `-Zunstable-options` to enable it. - -## Examples - -`rustc main.rs -Z unstable-options --print cfg=cfgs.txt` diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cc86a3d7475..dd43ee03383 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -20,7 +20,8 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, - clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, + clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, + AttributesExt, ImplKind, ItemId, Type, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -289,16 +290,14 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::TypeAlias> { let predicates = cx.tcx.explicit_predicates_of(did); - let type_ = clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()), - cx, - Some(did), - None, - ); + let ty = cx.tcx.type_of(did).instantiate_identity(); + let type_ = clean_middle_ty(ty::Binder::dummy(ty), cx, Some(did), None); + let inner_type = clean_ty_alias_inner_type(ty, cx); Box::new(clean::TypeAlias { type_, generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates), + inner_type, item_type: None, }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b584c32a4c7..1f6e832c7cb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -24,6 +24,7 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::TypeFolder; +use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, AdtKind, EarlyBinder, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -955,6 +956,43 @@ fn clean_ty_generics<'tcx>( } } +fn clean_ty_alias_inner_type<'tcx>( + ty: Ty<'tcx>, + cx: &mut DocContext<'tcx>, +) -> Option<TypeAliasInnerType> { + let ty::Adt(adt_def, args) = ty.kind() else { + return None; + }; + + Some(if adt_def.is_enum() { + let variants: rustc_index::IndexVec<_, _> = adt_def + .variants() + .iter() + .map(|variant| clean_variant_def_with_args(variant, args, cx)) + .collect(); + + TypeAliasInnerType::Enum { + variants, + is_non_exhaustive: adt_def.is_variant_list_non_exhaustive(), + } + } else { + let variant = adt_def + .variants() + .iter() + .next() + .unwrap_or_else(|| bug!("a struct or union should always have one variant def")); + + let fields: Vec<_> = + clean_variant_def_with_args(variant, args, cx).kind.inner_items().cloned().collect(); + + if adt_def.is_struct() { + TypeAliasInnerType::Struct { ctor_kind: variant.ctor_kind(), fields } + } else { + TypeAliasInnerType::Union { fields } + } + }) +} + fn clean_proc_macro<'tcx>( item: &hir::Item<'tcx>, name: &mut Symbol, @@ -1222,6 +1260,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext Box::new(TypeAlias { type_: clean_ty(default, cx), generics, + inner_type: None, item_type: Some(item_type), }), bounds, @@ -1264,7 +1303,12 @@ pub(crate) fn clean_impl_item<'tcx>( None, ); AssocTypeItem( - Box::new(TypeAlias { type_, generics, item_type: Some(item_type) }), + Box::new(TypeAlias { + type_, + generics, + inner_type: None, + item_type: Some(item_type), + }), Vec::new(), ) } @@ -1471,6 +1515,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( None, ), generics, + inner_type: None, item_type: None, }), bounds, @@ -1490,6 +1535,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( None, ), generics, + inner_type: None, item_type: None, }), // Associated types inside trait or inherent impls are not allowed to have @@ -2363,6 +2409,83 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont ) } +pub(crate) fn clean_variant_def_with_args<'tcx>( + variant: &ty::VariantDef, + args: &GenericArgsRef<'tcx>, + cx: &mut DocContext<'tcx>, +) -> Item { + let discriminant = match variant.discr { + ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), + ty::VariantDiscr::Relative(_) => None, + }; + + use rustc_middle::traits::ObligationCause; + use rustc_trait_selection::infer::TyCtxtInferExt; + use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; + + let infcx = cx.tcx.infer_ctxt().build(); + let kind = match variant.ctor_kind() { + Some(CtorKind::Const) => VariantKind::CLike, + Some(CtorKind::Fn) => VariantKind::Tuple( + variant + .fields + .iter() + .map(|field| { + let ty = cx.tcx.type_of(field.did).instantiate(cx.tcx, args); + + // normalize the type to only show concrete types + // note: we do not use try_normalize_erasing_regions since we + // do care about showing the regions + let ty = infcx + .at(&ObligationCause::dummy(), cx.param_env) + .query_normalize(ty) + .map(|normalized| normalized.value) + .unwrap_or(ty); + + clean_field_with_def_id( + field.did, + field.name, + clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None), + cx, + ) + }) + .collect(), + ), + None => VariantKind::Struct(VariantStruct { + fields: variant + .fields + .iter() + .map(|field| { + let ty = cx.tcx.type_of(field.did).instantiate(cx.tcx, args); + + // normalize the type to only show concrete types + // note: we do not use try_normalize_erasing_regions since we + // do care about showing the regions + let ty = infcx + .at(&ObligationCause::dummy(), cx.param_env) + .query_normalize(ty) + .map(|normalized| normalized.value) + .unwrap_or(ty); + + clean_field_with_def_id( + field.did, + field.name, + clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None), + cx, + ) + }) + .collect(), + }), + }; + + Item::from_def_id_and_parts( + variant.def_id, + Some(variant.name), + VariantItem(Variant { kind, discriminant }), + cx, + ) +} + fn clean_variant_data<'tcx>( variant: &hir::VariantData<'tcx>, disr_expr: &Option<hir::AnonConst>, @@ -2617,7 +2740,7 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::TyAlias(hir_ty, generics) => { *cx.current_type_aliases.entry(def_id).or_insert(0) += 1; let rustdoc_ty = clean_ty(hir_ty, cx); - let ty = clean_middle_ty( + let type_ = clean_middle_ty( ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None, @@ -2630,10 +2753,15 @@ fn clean_maybe_renamed_item<'tcx>( cx.current_type_aliases.remove(&def_id); } } + + let ty = cx.tcx.type_of(def_id).instantiate_identity(); + let inner_type = clean_ty_alias_inner_type(ty, cx); + TypeAliasItem(Box::new(TypeAlias { - type_: rustdoc_ty, generics, - item_type: Some(ty), + inner_type, + type_: rustdoc_ty, + item_type: Some(type_), })) } ItemKind::Enum(ref def, generics) => EnumItem(Enum { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9134d5268da..ff158fa8b4c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2231,9 +2231,19 @@ pub(crate) struct PathSegment { } #[derive(Clone, Debug)] +pub(crate) enum TypeAliasInnerType { + Enum { variants: IndexVec<VariantIdx, Item>, is_non_exhaustive: bool }, + Union { fields: Vec<Item> }, + Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> }, +} + +#[derive(Clone, Debug)] pub(crate) struct TypeAlias { pub(crate) type_: Type, pub(crate) generics: Generics, + /// Inner `AdtDef` type, ie `type TyKind = IrTyKind<Adt, Ty>`, + /// to be shown directly on the typedef page. + pub(crate) inner_type: Option<TypeAliasInnerType>, /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type /// alias instead of the final type. This will always have the final type, regardless of whether /// `type_` came from HIR or from metadata. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 1ce7efdfc20..974dc1c5135 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -157,6 +157,12 @@ pub(crate) struct Options { /// Note: this field is duplicated in `RenderOptions` because it's useful /// to have it in both places. pub(crate) unstable_features: rustc_feature::UnstableFeatures, + + /// All commandline args used to invoke the compiler, with @file args fully expanded. + /// This will only be used within debug info, e.g. in the pdb file on windows + /// This is mainly useful for other tools that reads that debuginfo to figure out + /// how to call the compiler with the same arguments. + pub(crate) expanded_args: Vec<String>, } impl fmt::Debug for Options { @@ -744,6 +750,7 @@ impl Options { json_unused_externs, scrape_examples_options, unstable_features, + expanded_args: args, }; let render_options = RenderOptions { output, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index eadff37b592..7cd25ef444b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -194,6 +194,7 @@ pub(crate) fn create_config( describe_lints, lint_cap, scrape_examples_options, + expanded_args, .. }: RustdocOptions, RenderOptions { document_private, .. }: &RenderOptions, @@ -291,6 +292,7 @@ pub(crate) fn create_config( make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, + expanded_args, } } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 36d5adb6304..bb7d26c541b 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -109,6 +109,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, + expanded_args: options.expanded_args.clone(), }; let test_args = options.test_args.clone(); diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index ceba643ed5f..cf11e2d7899 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -52,10 +52,31 @@ pub(crate) trait DocFolder: Sized { VariantItem(Variant { kind, discriminant }) } + TypeAliasItem(mut typealias) => { + typealias.inner_type = typealias.inner_type.map(|inner_type| match inner_type { + TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { + let variants = variants + .into_iter_enumerated() + .filter_map(|(_, x)| self.fold_item(x)) + .collect(); + + TypeAliasInnerType::Enum { variants, is_non_exhaustive } + } + TypeAliasInnerType::Union { fields } => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + TypeAliasInnerType::Union { fields } + } + TypeAliasInnerType::Struct { ctor_kind, fields } => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + TypeAliasInnerType::Struct { ctor_kind, fields } + } + }); + + TypeAliasItem(typealias) + } ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) - | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9a34e7cce8a..4c6e7dfb987 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -457,6 +457,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { | clean::StructItem(..) | clean::UnionItem(..) | clean::VariantItem(..) + | clean::TypeAliasItem(..) | clean::ImplItem(..) => { self.cache.parent_stack.push(ParentStackItem::new(&item)); (self.fold_item_recur(item), true) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 98cc38a10d4..a8d85fb6fb4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1574,7 +1574,6 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { map.insert("crate-search-div".into(), 1); // This is the list of IDs used in HTML generated in Rust (including the ones // used in tera template files). - map.insert("mainThemeStyle".into(), 1); map.insert("themeStyle".into(), 1); map.insert("settings-menu".into(), 1); map.insert("help-button".into(), 1); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index aef8f1a74fb..a85e8356c2f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -54,6 +54,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; use rustc_middle::middle::stability; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::TyCtxt; use rustc_span::{ symbol::{sym, Symbol}, @@ -62,6 +63,7 @@ use rustc_span::{ use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Serialize, Serializer}; +use crate::clean::types::TypeAliasItem; use crate::clean::{self, ItemId, RenderedLink, SelfTy}; use crate::error::Error; use crate::formats::cache::Cache; @@ -1139,8 +1141,40 @@ fn render_assoc_items_inner( info!("Documenting associated items of {:?}", containing_item.name); let shared = Rc::clone(&cx.shared); let cache = &shared.cache; - let Some(v) = cache.impls.get(&it) else { return }; - let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); + let tcx = cx.tcx(); + let av = if let TypeAliasItem(ait) = &*containing_item.kind && + let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) && + let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) && + let Some(mut av) = cache.impls.get(&aliased_type_defid).cloned() && + let Some(alias_def_id) = containing_item.item_id.as_def_id() + { + // This branch of the compiler compares types structually, but does + // not check trait bounds. That's probably fine, since type aliases + // don't normally constrain on them anyway. + // https://github.com/rust-lang/rust/issues/21903 + // + // FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification. + // Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress. + let aliased_ty = tcx.type_of(alias_def_id).skip_binder(); + let reject_cx = DeepRejectCtxt { + treat_obligation_params: TreatParams::AsCandidateKey, + }; + av.retain(|impl_| { + if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() { + reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder()) + } else { + false + } + }); + av + } else { + Vec::new() + }; + let blank = Vec::new(); + let v = cache.impls.get(&it).unwrap_or(&blank); + let (non_trait, traits): (Vec<_>, _) = + v.iter().chain(&av[..]).partition(|i| i.inner_impl().trait_.is_none()); + let mut saw_impls = FxHashSet::default(); if !non_trait.is_empty() { let mut tmp_buf = Buffer::html(); let (render_mode, id, class_html) = match what { @@ -1169,6 +1203,9 @@ fn render_assoc_items_inner( }; let mut impls_buf = Buffer::html(); for i in &non_trait { + if !saw_impls.insert(i.def_id()) { + continue; + } render_impl( &mut impls_buf, cx, @@ -1214,8 +1251,10 @@ fn render_assoc_items_inner( let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); - let (blanket_impl, concrete): (Vec<&Impl>, _) = - concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); + let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete + .into_iter() + .filter(|t| saw_impls.insert(t.def_id())) + .partition(|t| t.inner_impl().kind.is_blanket()); render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index cb78f903462..c6751c9585e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1237,6 +1237,75 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + if let Some(inner_type) = &t.inner_type { + write!( + w, + "<h2 id=\"aliased-type\" class=\"small-section-header\">\ + Aliased Type<a href=\"#aliased-type\" class=\"anchor\">§</a></h2>" + ); + + match inner_type { + clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { + let variants_iter = || variants.iter().filter(|i| !i.is_stripped()); + wrap_item(w, |w| { + let variants_len = variants.len(); + let variants_count = variants_iter().count(); + let has_stripped_entries = variants_len != variants_count; + + write!(w, "enum {}{}", it.name.unwrap(), t.generics.print(cx)); + render_enum_fields( + w, + cx, + Some(&t.generics), + variants_iter(), + variants_count, + has_stripped_entries, + *is_non_exhaustive, + ) + }); + item_variants(w, cx, it, variants_iter()); + } + clean::TypeAliasInnerType::Union { fields } => { + wrap_item(w, |w| { + let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); + let has_stripped_fields = fields.len() != fields_count; + + write!(w, "union {}{}", it.name.unwrap(), t.generics.print(cx)); + render_struct_fields( + w, + Some(&t.generics), + None, + fields, + "", + true, + has_stripped_fields, + cx, + ); + }); + item_fields(w, cx, it, fields, None); + } + clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { + wrap_item(w, |w| { + let fields_count = fields.iter().filter(|i| !i.is_stripped()).count(); + let has_stripped_fields = fields.len() != fields_count; + + write!(w, "struct {}{}", it.name.unwrap(), t.generics.print(cx)); + render_struct_fields( + w, + Some(&t.generics), + *ctor_kind, + fields, + "", + true, + has_stripped_fields, + cx, + ); + }); + item_fields(w, cx, it, fields, None); + } + } + } + let def_id = it.item_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -1315,6 +1384,12 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( s: &'a [clean::Item], ) -> impl fmt::Display + 'a + Captures<'cx> { display_fn(|f| { + if s.iter() + .all(|field| matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))) + { + return f.write_str("/* private fields */"); + } + for (i, ty) in s.iter().enumerate() { if i > 0 { f.write_str(", ")?; @@ -1332,7 +1407,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { let tcx = cx.tcx(); let count_variants = e.variants().count(); - wrap_item(w, |mut w| { + wrap_item(w, |w| { render_attributes_in_code(w, it, tcx); write!( w, @@ -1341,148 +1416,179 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: it.name.unwrap(), e.generics.print(cx), ); - if !print_where_clause_and_check(w, &e.generics, cx) { - // If there wasn't a `where` clause, we add a whitespace. - w.write_str(" "); - } + render_enum_fields( + w, + cx, + Some(&e.generics), + e.variants(), + count_variants, + e.has_stripped_entries(), + it.is_non_exhaustive(), + ); + }); - let variants_stripped = e.has_stripped_entries(); - if count_variants == 0 && !variants_stripped { - w.write_str("{}"); - } else { - w.write_str("{\n"); - let toggle = should_hide_fields(count_variants); - if toggle { - toggle_open(&mut w, format_args!("{count_variants} variants")); - } - for v in e.variants() { - w.write_str(" "); - let name = v.name.unwrap(); - match *v.kind { - // FIXME(#101337): Show discriminant - clean::VariantItem(ref var) => match var.kind { - clean::VariantKind::CLike => w.write_str(name.as_str()), - clean::VariantKind::Tuple(ref s) => { - write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); - } - clean::VariantKind::Struct(ref s) => { - render_struct(w, v, None, None, &s.fields, " ", false, cx); - } - }, - _ => unreachable!(), - } - w.write_str(",\n"); - } + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - if variants_stripped && !it.is_non_exhaustive() { - w.write_str(" // some variants omitted\n"); - } - if toggle { - toggle_close(&mut w); + if count_variants != 0 { + item_variants(w, cx, it, e.variants()); + } + let def_id = it.item_id.expect_def_id(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); +} + +fn render_enum_fields<'a>( + mut w: &mut Buffer, + cx: &mut Context<'_>, + g: Option<&clean::Generics>, + variants: impl Iterator<Item = &'a clean::Item>, + count_variants: usize, + has_stripped_entries: bool, + is_non_exhaustive: bool, +) { + if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) { + // If there wasn't a `where` clause, we add a whitespace. + w.write_str(" "); + } + + let variants_stripped = has_stripped_entries; + if count_variants == 0 && !variants_stripped { + w.write_str("{}"); + } else { + w.write_str("{\n"); + let toggle = should_hide_fields(count_variants); + if toggle { + toggle_open(&mut w, format_args!("{count_variants} variants")); + } + const TAB: &str = " "; + for v in variants { + w.write_str(TAB); + let name = v.name.unwrap(); + match *v.kind { + // FIXME(#101337): Show discriminant + clean::VariantItem(ref var) => match var.kind { + clean::VariantKind::CLike => w.write_str(name.as_str()), + clean::VariantKind::Tuple(ref s) => { + write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); + } + clean::VariantKind::Struct(ref s) => { + render_struct(w, v, None, None, &s.fields, TAB, false, cx); + } + }, + _ => unreachable!(), } - w.write_str("}"); + w.write_str(",\n"); } - }); - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + if variants_stripped && !is_non_exhaustive { + w.write_str(" // some variants omitted\n"); + } + if toggle { + toggle_close(&mut w); + } + w.write_str("}"); + } +} - if count_variants != 0 { +fn item_variants<'a>( + w: &mut Buffer, + cx: &mut Context<'_>, + it: &clean::Item, + variants: impl Iterator<Item = &'a clean::Item>, +) { + let tcx = cx.tcx(); + write!( + w, + "<h2 id=\"variants\" class=\"variants small-section-header\">\ + Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\ + </h2>\ + {}\ + <div class=\"variants\">", + document_non_exhaustive_header(it), + document_non_exhaustive(it) + ); + for variant in variants { + let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( w, - "<h2 id=\"variants\" class=\"variants small-section-header\">\ - Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\ - </h2>\ - {}\ - <div class=\"variants\">", - document_non_exhaustive_header(it), - document_non_exhaustive(it) + "<section id=\"{id}\" class=\"variant\">\ + <a href=\"#{id}\" class=\"anchor\">§</a>", ); - for variant in e.variants() { - let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); - write!( - w, - "<section id=\"{id}\" class=\"variant\">\ - <a href=\"#{id}\" class=\"anchor\">§</a>", - ); - render_stability_since_raw_with_extra( - w, - variant.stable_since(tcx), - variant.const_stability(tcx), - it.stable_since(tcx), - it.const_stable_since(tcx), - " rightside", - ); - write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); + render_stability_since_raw_with_extra( + w, + variant.stable_since(tcx), + variant.const_stability(tcx), + it.stable_since(tcx), + it.const_stable_since(tcx), + " rightside", + ); + write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); - let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; - if let clean::VariantKind::Tuple(ref s) = variant_data.kind { - write!(w, "({})", print_tuple_struct_fields(cx, s)); - } - w.write_str("</h3></section>"); - - let heading_and_fields = match &variant_data.kind { - clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), - clean::VariantKind::Tuple(fields) => { - // Documentation on tuple variant fields is rare, so to reduce noise we only emit - // the section if at least one field is documented. - if fields.iter().any(|f| !f.doc_value().is_empty()) { - Some(("Tuple Fields", fields)) - } else { - None - } + if let clean::VariantKind::Tuple(ref s) = variant_data.kind { + write!(w, "({})", print_tuple_struct_fields(cx, s)); + } + w.write_str("</h3></section>"); + + let heading_and_fields = match &variant_data.kind { + clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), + clean::VariantKind::Tuple(fields) => { + // Documentation on tuple variant fields is rare, so to reduce noise we only emit + // the section if at least one field is documented. + if fields.iter().any(|f| !f.doc_value().is_empty()) { + Some(("Tuple Fields", fields)) + } else { + None } - clean::VariantKind::CLike => None, - }; + } + clean::VariantKind::CLike => None, + }; - if let Some((heading, fields)) = heading_and_fields { - let variant_id = - cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap())); - write!( - w, - "<div class=\"sub-variant\" id=\"{variant_id}\">\ - <h4>{heading}</h4>\ - {}", - document_non_exhaustive(variant) - ); - for field in fields { - match *field.kind { - clean::StrippedItem(box clean::StructFieldItem(_)) => {} - clean::StructFieldItem(ref ty) => { - let id = cx.derive_id(format!( - "variant.{}.field.{}", - variant.name.unwrap(), - field.name.unwrap() - )); - write!( - w, - "<div class=\"sub-variant-field\">\ + if let Some((heading, fields)) = heading_and_fields { + let variant_id = + cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap())); + write!( + w, + "<div class=\"sub-variant\" id=\"{variant_id}\">\ + <h4>{heading}</h4>\ + {}", + document_non_exhaustive(variant) + ); + for field in fields { + match *field.kind { + clean::StrippedItem(box clean::StructFieldItem(_)) => {} + clean::StructFieldItem(ref ty) => { + let id = cx.derive_id(format!( + "variant.{}.field.{}", + variant.name.unwrap(), + field.name.unwrap() + )); + write!( + w, + "<div class=\"sub-variant-field\">\ <span id=\"{id}\" class=\"small-section-header\">\ <a href=\"#{id}\" class=\"anchor field\">§</a>\ <code>{f}: {t}</code>\ </span>", - f = field.name.unwrap(), - t = ty.print(cx), - ); - write!( - w, - "{}</div>", - document(cx, field, Some(variant), HeadingOffset::H5) - ); - } - _ => unreachable!(), + f = field.name.unwrap(), + t = ty.print(cx), + ); + write!( + w, + "{}</div>", + document(cx, field, Some(variant), HeadingOffset::H5) + ); } + _ => unreachable!(), } - w.write_str("</div>"); } - - write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); + w.write_str("</div>"); } - write!(w, "</div>"); + + write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); } - let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); - write!(w, "{}", document_type_layout(cx, def_id)); + write!(w, "</div>"); } fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { @@ -1593,15 +1699,28 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - let mut fields = s - .fields + item_fields(w, cx, it, &s.fields, s.ctor_kind); + + let def_id = it.item_id.expect_def_id(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); +} + +fn item_fields( + w: &mut Buffer, + cx: &mut Context<'_>, + it: &clean::Item, + fields: &Vec<clean::Item>, + ctor_kind: Option<CtorKind>, +) { + let mut fields = fields .iter() .filter_map(|f| match *f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) .peekable(); - if let None | Some(CtorKind::Fn) = s.ctor_kind { + if let None | Some(CtorKind::Fn) = ctor_kind { if fields.peek().is_some() { write!( w, @@ -1609,7 +1728,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean {}{}<a href=\"#fields\" class=\"anchor\">§</a>\ </h2>\ {}", - if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, + if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, document_non_exhaustive_header(it), document_non_exhaustive(it) ); @@ -1630,9 +1749,6 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } } - let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); - write!(w, "{}", document_type_layout(cx, def_id)); } fn item_static(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1871,7 +1987,7 @@ fn render_union<'a, 'cx: 'a>( } fn render_struct( - mut w: &mut Buffer, + w: &mut Buffer, it: &clean::Item, g: Option<&clean::Generics>, ty: Option<CtorKind>, @@ -1891,6 +2007,29 @@ fn render_struct( if let Some(g) = g { write!(w, "{}", g.print(cx)) } + render_struct_fields( + w, + g, + ty, + fields, + tab, + structhead, + it.has_stripped_entries().unwrap_or(false), + cx, + ) +} + +fn render_struct_fields( + mut w: &mut Buffer, + g: Option<&clean::Generics>, + ty: Option<CtorKind>, + fields: &[clean::Item], + tab: &str, + structhead: bool, + has_stripped_entries: bool, + cx: &Context<'_>, +) { + let tcx = cx.tcx(); match ty { None => { let where_displayed = @@ -1922,11 +2061,11 @@ fn render_struct( } if has_visible_fields { - if it.has_stripped_entries().unwrap() { + if has_stripped_entries { write!(w, "\n{tab} /* private fields */"); } write!(w, "\n{tab}"); - } else if it.has_stripped_entries().unwrap() { + } else if has_stripped_entries { write!(w, " /* private fields */ "); } if toggle { @@ -1936,21 +2075,31 @@ fn render_struct( } Some(CtorKind::Fn) => { w.write_str("("); - for (i, field) in fields.iter().enumerate() { - if i > 0 { - w.write_str(", "); - } - match *field.kind { - clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), - clean::StructFieldItem(ref ty) => { - write!( - w, - "{}{}", - visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - ty.print(cx), - ) + if fields.iter().all(|field| { + matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + }) { + write!(w, "/* private fields */"); + } else { + for (i, field) in fields.iter().enumerate() { + if i > 0 { + w.write_str(", "); + } + match *field.kind { + clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), + clean::StructFieldItem(ref ty) => { + write!( + w, + "{}{}", + visibility_print_with_space( + field.visibility(tcx), + field.item_id, + cx + ), + ty.print(cx), + ) + } + _ => unreachable!(), } - _ => unreachable!(), } } w.write_str(")"); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index b96b1536156..fce31a8423d 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -82,7 +82,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf clean::PrimitiveItem(_) => sidebar_primitive(cx, it), clean::UnionItem(ref u) => sidebar_union(cx, it, u), clean::EnumItem(ref e) => sidebar_enum(cx, it, e), - clean::TypeAliasItem(_) => sidebar_type_alias(cx, it), + clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t), clean::ModuleItem(ref m) => vec![sidebar_module(&m.items)], clean::ForeignTypeItem => sidebar_foreign_type(cx, it), _ => vec![], @@ -230,8 +230,32 @@ fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec<LinkBl } } -fn sidebar_type_alias<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec<LinkBlock<'a>> { +fn sidebar_type_alias<'a>( + cx: &'a Context<'_>, + it: &'a clean::Item, + t: &'a clean::TypeAlias, +) -> Vec<LinkBlock<'a>> { let mut items = vec![]; + if let Some(inner_type) = &t.inner_type { + match inner_type { + clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive: _ } => { + let mut variants = variants + .iter() + .filter(|i| !i.is_stripped()) + .filter_map(|v| v.name) + .map(|name| Link::new(format!("variant.{name}"), name.to_string())) + .collect::<Vec<_>>(); + variants.sort_unstable(); + + items.push(LinkBlock::new(Link::new("variants", "Variants"), variants)); + } + clean::TypeAliasInnerType::Union { fields } + | clean::TypeAliasInnerType::Struct { ctor_kind: _, fields } => { + let fields = get_struct_fields_name(fields); + items.push(LinkBlock::new(Link::new("fields", "Fields"), fields)); + } + } + } sidebar_assoc_items(cx, it, &mut items); items } diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 60ccfe4da44..8cb43634377 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -15,8 +15,7 @@ <link rel="stylesheet" {#+ #} href="{{static_root_path|safe}}{{files.normalize_css}}"> {# #} <link rel="stylesheet" {#+ #} - href="{{static_root_path|safe}}{{files.rustdoc_css}}" {#+ #} - id="mainThemeStyle"> {# #} + href="{{static_root_path|safe}}{{files.rustdoc_css}}"> {# #} {% if !layout.default_settings.is_empty() %} <script id="default-settings" {#+ #} {%~ for (k, v) in layout.default_settings ~%} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 0c18f5687f5..08865015960 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -789,7 +789,7 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind impl FromWithTcx<Box<clean::TypeAlias>> for TypeAlias { fn from_tcx(type_alias: Box<clean::TypeAlias>, tcx: TyCtxt<'_>) -> Self { - let clean::TypeAlias { type_, generics, item_type: _ } = *type_alias; + let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = *type_alias; TypeAlias { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } } } diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr1.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs index 6ab73569c63..6ab73569c63 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr1.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr1.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr index 133e4b2c16a..21e403b47f8 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr1.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a null reference - --> $DIR/cast_fn_ptr1.rs:LL:CC + --> $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC | LL | g(0usize as *const i32) | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference @@ -7,7 +7,7 @@ LL | g(0usize as *const i32) = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC + = note: inside `main` at $DIR/cast_fn_ptr_invalid_callee_arg.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs new file mode 100644 index 00000000000..7cdc15c6094 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs @@ -0,0 +1,28 @@ +#![allow(internal_features)] +#![feature(core_intrinsics, custom_mir)] + +use std::intrinsics::mir::*; +use std::num::NonZeroU32; +use std::ptr; + +// This function supposedly returns a NonZeroU32, but actually returns something invalid in a way that +// never materializes a bad NonZeroU32 value: we take a pointer to the return place and cast the pointer +// type. That way we never get an "invalid value constructed" error inside the function, it can +// only possibly be detected when the return value is passed to the caller. +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn f() -> NonZeroU32 { + mir! { + { + let tmp = ptr::addr_of_mut!(RET); + let ptr = tmp as *mut u32; + *ptr = 0; + Return() + } + } +} + +fn main() { + let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZeroU32) }; + // There's a NonZeroU32-to-u32 transmute happening here + f(); //~ERROR: expected something greater or equal to 1 +} diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr new file mode 100644 index 00000000000..ccfb8890939 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1 + --> $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC + | +LL | f(); + | ^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/cast_fn_ptr_invalid_callee_ret.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs new file mode 100644 index 00000000000..ee80186d4b5 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs @@ -0,0 +1,34 @@ +#![allow(internal_features)] +#![feature(core_intrinsics, custom_mir)] + +use std::intrinsics::mir::*; +use std::num::NonZeroU32; +use std::ptr; + +fn f(c: u32) { + println!("{c}"); +} + +// Call that function in a bad way, with an invalid NonZeroU32, but without +// ever materializing this as a NonZeroU32 value outside the call itself. +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn call(f: fn(NonZeroU32)) { + mir! { + let _res: (); + { + let c = 0; + let tmp = ptr::addr_of!(c); + let ptr = tmp as *const NonZeroU32; + // The call site now is a NonZeroU32-to-u32 transmute. + Call(_res = f(*ptr), retblock) //~ERROR: expected something greater or equal to 1 + } + retblock = { + Return() + } + } +} + +fn main() { + let f: fn(NonZeroU32) = unsafe { std::mem::transmute(f as fn(u32)) }; + call(f); +} diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr new file mode 100644 index 00000000000..234c2804008 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1 + --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC + | +LL | Call(_res = f(*ptr), retblock) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `call` at $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC +note: inside `main` + --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC + | +LL | call(f); + | ^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr2.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.rs index 64ddb563be5..64ddb563be5 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr2.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.rs diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr2.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr index 21001f2b460..bd9866acbd4 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr2.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a null reference - --> $DIR/cast_fn_ptr2.rs:LL:CC + --> $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC | LL | let _x = g(); | ^^^ constructing invalid value: encountered a null reference @@ -7,7 +7,7 @@ LL | let _x = g(); = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC + = note: inside `main` at $DIR/cast_fn_ptr_invalid_caller_ret.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs index 68132638759..1c9d33dcc8e 100644 --- a/tests/run-make-fulldeps/issue-19371/foo.rs +++ b/tests/run-make-fulldeps/issue-19371/foo.rs @@ -61,6 +61,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { override_queries: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), + expanded_args: Default::default(), }; interface::run_compiler(config, |compiler| { diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile new file mode 100644 index 00000000000..a7be301a5b0 --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile @@ -0,0 +1,16 @@ +include ../tools.mk + +# only-windows-msvc + +# tests if the pdb contains the following information in the LF_BUILDINFO: +# 1. the commandline args to compile it (cmd) +# 2. full path to the compiler (cl) + +# we just do a stringsearch on the pdb, as these need to show up at least once, as the LF_BUILDINFO is created for each cgu +# actual parsing would be better, but this is a simple and good enough solution for now + +all: + $(RUSTC_ORIGINAL) main.rs -g --crate-name my_crate_name --crate-type bin -C metadata=dc9ef878b0a48666 --out-dir $(TMPDIR) + cat '$(TMPDIR)/my_crate_name.pdb' | grep -F '$(RUSTC_ORIGINAL)' +# using a file containing the string so I don't have problems with escaping quotes and spaces + cat '$(TMPDIR)/my_crate_name.pdb' | grep -f 'stringlist.txt' diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/main.rs b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs new file mode 100644 index 00000000000..f79c691f085 --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt new file mode 100644 index 00000000000..634e9f19e89 --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt @@ -0,0 +1 @@ +"main.rs" "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-C" "metadata=dc9ef878b0a48666" "--out-dir" \ No newline at end of file diff --git a/tests/run-make/print-cfg/Makefile b/tests/run-make/print-cfg/Makefile index 654c303b3e2..6b153e5b54e 100644 --- a/tests/run-make/print-cfg/Makefile +++ b/tests/run-make/print-cfg/Makefile @@ -13,19 +13,19 @@ all: default output_to_file output_to_file: # Backend-independent, printed by rustc_driver_impl/src/lib.rs - $(RUSTC) --target x86_64-pc-windows-gnu --print cfg=$(TMPDIR)/cfg.txt -Z unstable-options + $(RUSTC) --target x86_64-pc-windows-gnu --print cfg=$(TMPDIR)/cfg.txt $(CGREP) windows < $(TMPDIR)/cfg.txt # Printed from CodegenBackend trait impl in rustc_codegen_llvm/src/lib.rs - $(RUSTC) --print relocation-models=$(TMPDIR)/relocation-models.txt -Z unstable-options + $(RUSTC) --print relocation-models=$(TMPDIR)/relocation-models.txt $(CGREP) dynamic-no-pic < $(TMPDIR)/relocation-models.txt # Printed by compiler/rustc_codegen_llvm/src/llvm_util.rs - $(RUSTC) --target wasm32-unknown-unknown --print target-features=$(TMPDIR)/target-features.txt -Z unstable-options + $(RUSTC) --target wasm32-unknown-unknown --print target-features=$(TMPDIR)/target-features.txt $(CGREP) reference-types < $(TMPDIR)/target-features.txt # Printed by C++ code in rustc_llvm/llvm-wrapper/PassWrapper.cpp - $(RUSTC) --target wasm32-unknown-unknown --print target-cpus=$(TMPDIR)/target-cpus.txt -Z unstable-options + $(RUSTC) --target wasm32-unknown-unknown --print target-cpus=$(TMPDIR)/target-cpus.txt $(CGREP) generic < $(TMPDIR)/target-cpus.txt ifdef IS_WINDOWS diff --git a/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs b/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs new file mode 100644 index 00000000000..f4e020b3b95 --- /dev/null +++ b/tests/rustdoc/auxiliary/cross_crate_generic_typedef.rs @@ -0,0 +1,5 @@ +pub struct InlineOne<A> { + pub inline: A +} + +pub type InlineU64 = InlineOne<u64>; diff --git a/tests/rustdoc/const-generics/const-generic-defaults.rs b/tests/rustdoc/const-generics/const-generic-defaults.rs index f781c6a62f2..7a0a794112d 100644 --- a/tests/rustdoc/const-generics/const-generic-defaults.rs +++ b/tests/rustdoc/const-generics/const-generic-defaults.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] // @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \ -// 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);' +// 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(' pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T); diff --git a/tests/rustdoc/const-generics/const-generics-docs.rs b/tests/rustdoc/const-generics/const-generics-docs.rs index 828486a41d4..70a9518f05b 100644 --- a/tests/rustdoc/const-generics/const-generics-docs.rs +++ b/tests/rustdoc/const-generics/const-generics-docs.rs @@ -33,7 +33,7 @@ impl<const N: usize> Trait<N> for [u8; N] {} // @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \ // 'pub struct Foo<const N: usize> where u8: Trait<N>' pub struct Foo<const N: usize> where u8: Trait<N>; -// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar<T, const N: usize>(_)' +// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar<T, const N: usize>(' pub struct Bar<T, const N: usize>([T; N]); // @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>' @@ -92,7 +92,7 @@ macro_rules! define_me { } // @has foo/struct.Foz.html '//pre[@class="rust item-decl"]' \ -// 'pub struct Foz<const N: usize>(_);' +// 'pub struct Foz<const N: usize>(/* private fields */);' define_me!(Foz<N>); trait Q { diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/issue-32077-type-alias-impls.rs new file mode 100644 index 00000000000..555d0579bee --- /dev/null +++ b/tests/rustdoc/issue-32077-type-alias-impls.rs @@ -0,0 +1,59 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/32077>. + +#![crate_name = "foo"] + +pub struct GenericStruct<T>(T); + +impl<T> GenericStruct<T> { + pub fn on_gen(arg: T) {} +} + +impl GenericStruct<u32> { + pub fn on_u32(arg: u32) {} +} + +pub trait Foo {} +pub trait Bar {} + +impl<T> Foo for GenericStruct<T> {} +impl Bar for GenericStruct<u32> {} + +// @has 'foo/type.TypedefStruct.html' +// We check that we have the implementation of the type alias itself. +// @has - '//*[@id="impl-TypedefStruct"]/h3' 'impl TypedefStruct' +// @has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()' +// @has - '//*[@id="impl-GenericStruct%3CT%3E"]/h3' 'impl<T> GenericStruct<T>' +// @has - '//*[@id="method.on_gen"]/h4' 'pub fn on_gen(arg: T)' +// @has - '//*[@id="impl-Foo-for-GenericStruct%3CT%3E"]/h3' 'impl<T> Foo for GenericStruct<T>' +// This trait implementation doesn't match the type alias parameters so shouldn't appear in docs. +// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}' +// Same goes for the `Deref` impl. +// @!has - '//h2' 'Methods from Deref<Target = u32>' +pub type TypedefStruct = GenericStruct<u8>; + +impl TypedefStruct { + pub fn on_alias() {} +} + +impl std::ops::Deref for GenericStruct<u32> { + type Target = u32; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct Wrap<T>(GenericStruct<T>); + +// @has 'foo/type.Alias.html' +// @has - '//h2' 'Methods from Deref<Target = u32>' +// @has - '//*[@id="impl-Deref-for-Wrap%3CT%3E"]/h3' 'impl<T> Deref for Wrap<T>' +pub type Alias = Wrap<u32>; + +impl<T> std::ops::Deref for Wrap<T> { + type Target = GenericStruct<T>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/rustdoc/issue-88600.rs b/tests/rustdoc/issue-88600.rs index db0d102b741..f89af472f6e 100644 --- a/tests/rustdoc/issue-88600.rs +++ b/tests/rustdoc/issue-88600.rs @@ -8,10 +8,10 @@ pub struct S; // @has issue_88600/enum.FooEnum.html pub enum FooEnum { - // @has - '//*[@id="variant.HiddenTupleItem"]//h3' 'HiddenTupleItem(_)' + // @has - '//*[@id="variant.HiddenTupleItem"]//h3' 'HiddenTupleItem(/* private fields */)' // @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0 HiddenTupleItem(#[doc(hidden)] H), - // @has - '//*[@id="variant.MultipleHidden"]//h3' 'MultipleHidden(_, _)' + // @has - '//*[@id="variant.MultipleHidden"]//h3' 'MultipleHidden(/* private fields */)' // @count - '//*[@id="variant.MultipleHidden.field.0"]' 0 // @count - '//*[@id="variant.MultipleHidden.field.1"]' 0 MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H), diff --git a/tests/rustdoc/private-fields-tuple-struct.rs b/tests/rustdoc/private-fields-tuple-struct.rs new file mode 100644 index 00000000000..c6989dd8cdf --- /dev/null +++ b/tests/rustdoc/private-fields-tuple-struct.rs @@ -0,0 +1,15 @@ +// This test checks the diplay of "/* private fields */" sentence in tuple structs. +#![crate_name = "foo"] + +// @has 'foo/struct.A.html' '//*[@class="rust item-decl"]/code' 'pub struct A(pub u8, _);' +pub struct A(pub u8, u8); +// @has 'foo/struct.B.html' '//*[@class="rust item-decl"]/code' 'pub struct B(_, pub u8);' +pub struct B(u8, pub u8); +// @has 'foo/struct.C.html' '//*[@class="rust item-decl"]/code' 'pub struct C(_, pub u8, _);' +pub struct C(u8, pub u8, u8); +// @has 'foo/struct.D.html' '//*[@class="rust item-decl"]/code' 'pub struct D(pub u8, _, pub u8);' +pub struct D(pub u8, u8, pub u8); +// @has 'foo/struct.E.html' '//*[@class="rust item-decl"]/code' 'pub struct E(/* private fields */);' +pub struct E(u8); +// @has 'foo/struct.F.html' '//*[@class="rust item-decl"]/code' 'pub struct F(/* private fields */);' +pub struct F(u8, u8); diff --git a/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs b/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs new file mode 100644 index 00000000000..ff84352d716 --- /dev/null +++ b/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs @@ -0,0 +1,34 @@ +#![crate_name = "inner_types_lazy"] + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +// @has 'inner_types_lazy/struct.Pair.html' +pub struct Pair<A, B> { + pub first: A, + pub second: B, +} + +// @has 'inner_types_lazy/type.ReversedTypesPair.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @count - '//span[@class="where fmt-newline"]' 0 +pub type ReversedTypesPair<Q, R> = Pair<R, Q>; + +// @has 'inner_types_lazy/type.ReadWrite.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @count - '//span[@class="where fmt-newline"]' 2 +pub type ReadWrite<R, W> = Pair<R, W> +where + R: std::io::Read, + W: std::io::Write; + +// @has 'inner_types_lazy/type.VecPair.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @count - '//span[@class="where fmt-newline"]' 0 +pub type VecPair<U, V> = Pair<Vec<U>, Vec<V>>; diff --git a/tests/rustdoc/typedef-inner-variants.rs b/tests/rustdoc/typedef-inner-variants.rs new file mode 100644 index 00000000000..b734714fd64 --- /dev/null +++ b/tests/rustdoc/typedef-inner-variants.rs @@ -0,0 +1,119 @@ +// This test checks different combinations of structs, enums, and unions +// for the "Show Aliased Type" feature on type definition. + +#![crate_name = "inner_variants"] + +// aux-build:cross_crate_generic_typedef.rs +extern crate cross_crate_generic_typedef; + +pub struct Adt; +pub struct Ty; +pub struct TyCtxt; + +pub trait Interner { + type Adt; + type Ty; +} + +impl Interner for TyCtxt { + type Adt = Adt; + type Ty = Ty; +} + +// @has 'inner_variants/type.AliasTy.html' +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 0 +pub type AliasTy = Ty; + +// @has 'inner_variants/enum.IrTyKind.html' +pub enum IrTyKind<A, I: Interner> { + /// Doc comment for AdtKind + AdtKind(I::Adt), + /// and another one for TyKind + TyKind(I::Adt, <I as Interner>::Ty), + // no comment + StructKind { a: A, }, + #[doc(hidden)] + Unspecified, +} + +// @has 'inner_variants/type.NearlyTyKind.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 1 +// @count - '//*[@id="fields"]' 0 +pub type NearlyTyKind<A> = IrTyKind<A, TyCtxt>; + +// @has 'inner_variants/type.TyKind.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 1 +// @count - '//*[@id="fields"]' 0 +// @count - '//*[@class="variant"]' 3 +// @matches - '//pre[@class="rust item-decl"]//code' "enum TyKind" +// @has - '//pre[@class="rust item-decl"]//code/a[1]' "Adt" +// @has - '//pre[@class="rust item-decl"]//code/a[2]' "Adt" +// @has - '//pre[@class="rust item-decl"]//code/a[3]' "Ty" +// @has - '//pre[@class="rust item-decl"]//code/a[4]' "i64" +pub type TyKind = IrTyKind<i64, TyCtxt>; + +// @has 'inner_variants/union.OneOr.html' +pub union OneOr<A: Copy> { + pub one: i64, + pub or: A, +} + +// @has 'inner_variants/type.OneOrF64.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @count - '//*[@class="structfield small-section-header"]' 2 +// @matches - '//pre[@class="rust item-decl"]//code' "union OneOrF64" +pub type OneOrF64 = OneOr<f64>; + +// @has 'inner_variants/struct.One.html' +pub struct One<T> { + pub val: T, + #[doc(hidden)] + pub __hidden: T, + __private: T, +} + +// @has 'inner_variants/type.OneU64.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @count - '//*[@class="structfield small-section-header"]' 1 +// @matches - '//pre[@class="rust item-decl"]//code' "struct OneU64" +// @matches - '//pre[@class="rust item-decl"]//code' "pub val" +pub type OneU64 = One<u64>; + +// @has 'inner_variants/struct.OnceA.html' +pub struct OnceA<'a, A> { + pub a: &'a A, +} + +// @has 'inner_variants/type.Once.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @matches - '//pre[@class="rust item-decl"]//code' "struct Once<'a>" +// @matches - '//pre[@class="rust item-decl"]//code' "&'a" +pub type Once<'a> = OnceA<'a, i64>; + +// @has 'inner_variants/struct.HighlyGenericStruct.html' +pub struct HighlyGenericStruct<A, B, C, D> { + pub z: (A, B, C, D) +} + +// @has 'inner_variants/type.HighlyGenericAABB.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +// @matches - '//pre[@class="rust item-decl"]//code' "struct HighlyGenericAABB<A, B>" +// @matches - '//pre[@class="rust item-decl"]//code' "pub z" +pub type HighlyGenericAABB<A, B> = HighlyGenericStruct<A, A, B, B>; + +// @has 'inner_variants/type.InlineU64.html' +// @count - '//*[@id="aliased-type"]' 1 +// @count - '//*[@id="variants"]' 0 +// @count - '//*[@id="fields"]' 1 +pub use cross_crate_generic_typedef::InlineU64; diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html index 3e72ba2b74f..46708b9e4e9 100644 --- a/tests/rustdoc/where.SWhere_Simd_item-decl.html +++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html @@ -1,3 +1,3 @@ -<pre class="rust item-decl"><code>pub struct Simd<T>(_) +<pre class="rust item-decl"><code>pub struct Simd<T>(/* private fields */) <span class="where">where T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre> diff --git a/tests/rustdoc/where.alpha_trait_decl.html b/tests/rustdoc/where.alpha_trait_decl.html index a7700055c9a..0c0b2d1ceca 100644 --- a/tests/rustdoc/where.alpha_trait_decl.html +++ b/tests/rustdoc/where.alpha_trait_decl.html @@ -1,3 +1,3 @@ -<code>pub struct Alpha<A>(_) +<code>pub struct Alpha<A>(/* private fields */) <span class="where">where A: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code> \ No newline at end of file diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs index 2aa9c8b5461..aea02c14039 100644 --- a/tests/rustdoc/where.rs +++ b/tests/rustdoc/where.rs @@ -4,7 +4,7 @@ use std::io::Lines; pub trait MyTrait { fn dummy(&self) { } } -// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait" +// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(/* private fields */) where A: MyTrait" // @snapshot alpha_trait_decl - '//*[@class="rust item-decl"]/code' pub struct Alpha<A>(A) where A: MyTrait; // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait" diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index c2da4f57696..edce1045e24 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -13,12 +13,12 @@ error: future cannot be sent between threads safely LL | is_send(foo::<T>()); | ^^^^^^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>` + = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>> { <T as Foo>::method() }` note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/basic.rs:13:5 | LL | T::method().await?; - | ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>>`, which is not `Send` + | ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>> { <T as Foo>::method() }`, which is not `Send` note: required by a bound in `is_send` --> $DIR/basic.rs:17:20 | diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr new file mode 100644 index 00000000000..3b63ec45804 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr @@ -0,0 +1,27 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:8:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:23:11 + | +LL | build(Bar); + | ----- ^^^ `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Send` is not implemented for `impl Future<Output = ()> { <_ as Foo>::bar() }` +note: required by a bound in `build` + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:20:39 + | +LL | fn build<T>(_: T) where T: Foo<bar(): Send> {} + | ^^^^ required by this bound in `build` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr new file mode 100644 index 00000000000..6fab7178767 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:8:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs new file mode 100644 index 00000000000..b2cd9707db9 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs @@ -0,0 +1,24 @@ +// revisions: current next +//[current] known-bug: #109924 +//[next] check-pass +//[next] compile-flags: -Ztrait-solver=next +// edition:2021 + +#![feature(async_fn_in_trait)] +#![feature(return_type_notation)] +//[next]~^ WARN the feature `return_type_notation` is incomplete + +trait Foo { + async fn bar(&self); +} + +struct Bar; +impl Foo for Bar { + async fn bar(&self) {} +} + +fn build<T>(_: T) where T: Foo<bar(): Send> {} + +fn main() { + build(Bar); +} diff --git a/tests/ui/consts/drop-maybe_uninit.rs b/tests/ui/consts/drop-maybe_uninit.rs new file mode 100644 index 00000000000..2fdeae5f185 --- /dev/null +++ b/tests/ui/consts/drop-maybe_uninit.rs @@ -0,0 +1,17 @@ +// build-pass + +pub const fn f<T, const N: usize>(_: [std::mem::MaybeUninit<T>; N]) {} + +pub struct Blubb<T>(*const T); + +pub const fn g<T, const N: usize>(_: [Blubb<T>; N]) {} + +pub struct Blorb<const N: usize>([String; N]); + +pub const fn h(_: Blorb<0>) {} + +pub struct Wrap(Blorb<0>); + +pub const fn i(_: Wrap) {} + +fn main() {} diff --git a/tests/ui/feature-gates/print-with-path.cfg.stderr b/tests/ui/feature-gates/print-with-path.cfg.stderr deleted file mode 100644 index a6c51baa320..00000000000 --- a/tests/ui/feature-gates/print-with-path.cfg.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Z unstable-options` flag must also be passed to enable the path print option - diff --git a/tests/ui/feature-gates/print-with-path.rs b/tests/ui/feature-gates/print-with-path.rs deleted file mode 100644 index f929c14c218..00000000000 --- a/tests/ui/feature-gates/print-with-path.rs +++ /dev/null @@ -1,7 +0,0 @@ -// check-fail -// revisions: cfg target-features target-cpus -// [cfg]compile-flags: --print cfg=cfg.txt -// [target-cpus]compile-flags: --print target-cpu=target_cpu.txt -// [target-features]compile-flags: --print target-features=target_features.txt - -fn main() {} diff --git a/tests/ui/feature-gates/print-with-path.target-cpus.stderr b/tests/ui/feature-gates/print-with-path.target-cpus.stderr deleted file mode 100644 index a6c51baa320..00000000000 --- a/tests/ui/feature-gates/print-with-path.target-cpus.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Z unstable-options` flag must also be passed to enable the path print option - diff --git a/tests/ui/feature-gates/print-with-path.target-features.stderr b/tests/ui/feature-gates/print-with-path.target-features.stderr deleted file mode 100644 index a6c51baa320..00000000000 --- a/tests/ui/feature-gates/print-with-path.target-features.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Z unstable-options` flag must also be passed to enable the path print option - diff --git a/tests/ui/privacy/private-bounds-locally-allowed.rs b/tests/ui/privacy/private-bounds-locally-allowed.rs new file mode 100644 index 00000000000..96a007a64f6 --- /dev/null +++ b/tests/ui/privacy/private-bounds-locally-allowed.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: --crate-type=lib + +#[allow(private_bounds)] +pub trait Foo: FooImpl {} + +trait FooImpl {} diff --git a/tests/ui/trait-bounds/issue-82038.rs b/tests/ui/trait-bounds/issue-82038.rs new file mode 100644 index 00000000000..11de714faf0 --- /dev/null +++ b/tests/ui/trait-bounds/issue-82038.rs @@ -0,0 +1,9 @@ +// Failed bound `bool: Foo` must not point at the `Self: Clone` line + +trait Foo { + fn my_method() where Self: Clone; +} + +fn main() { + <bool as Foo>::my_method(); //~ERROR [E0277] +} diff --git a/tests/ui/trait-bounds/issue-82038.stderr b/tests/ui/trait-bounds/issue-82038.stderr new file mode 100644 index 00000000000..f37e3286f4b --- /dev/null +++ b/tests/ui/trait-bounds/issue-82038.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `bool: Foo` is not satisfied + --> $DIR/issue-82038.rs:8:6 + | +LL | <bool as Foo>::my_method(); + | ^^^^ the trait `Foo` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/object/enforce-supertrait-projection.rs b/tests/ui/traits/object/enforce-supertrait-projection.rs index 2c9b41eea2a..0ea944ec2df 100644 --- a/tests/ui/traits/object/enforce-supertrait-projection.rs +++ b/tests/ui/traits/object/enforce-supertrait-projection.rs @@ -7,7 +7,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {} fn transmute<A, B>(x: A) -> B { foo::<A, B, dyn Trait<A = A, B = B>>(x) - //~^ ERROR type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B` + //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` } fn foo<A, B, T: ?Sized>(x: T::A) -> B diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr index 848b4e69a4b..2fb94d34896 100644 --- a/tests/ui/traits/object/enforce-supertrait-projection.stderr +++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<dyn Trait<B = B, A = A> as SuperTrait>::A == B` +error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B` --> $DIR/enforce-supertrait-projection.rs:9:17 | LL | fn transmute<A, B>(x: A) -> B { diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.rs b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.rs new file mode 100644 index 00000000000..c6f9e345618 --- /dev/null +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.rs @@ -0,0 +1,15 @@ +fn use_iterator<I>(itr: I) +where + I: IntoIterator<Item = i32>, +{ +} + +fn pass_iterator<I>(i: &dyn IntoIterator<Item = i32, IntoIter = I>) +where + I: Iterator<Item = i32>, +{ + use_iterator(i); + //~^ ERROR `&dyn IntoIterator<IntoIter = I, Item = i32>` is not an iterator +} + +fn main() {} diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr new file mode 100644 index 00000000000..bd0e7ca2c02 --- /dev/null +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr @@ -0,0 +1,22 @@ +error[E0277]: `&dyn IntoIterator<IntoIter = I, Item = i32>` is not an iterator + --> $DIR/dont-suggest-unsize-deref.rs:11:18 + | +LL | use_iterator(i); + | ------------ ^ `&dyn IntoIterator<IntoIter = I, Item = i32>` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `&dyn IntoIterator<IntoIter = I, Item = i32>` + = note: required for `&dyn IntoIterator<IntoIter = I, Item = i32>` to implement `IntoIterator` +note: required by a bound in `use_iterator` + --> $DIR/dont-suggest-unsize-deref.rs:3:8 + | +LL | fn use_iterator<I>(itr: I) + | ------------ required by a bound in this function +LL | where +LL | I: IntoIterator<Item = i32>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `use_iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/issue-39029.fixed b/tests/ui/traits/suggest-dereferences/issue-39029.fixed index a1abf668b8b..a1abf668b8b 100644 --- a/tests/ui/traits/suggest-deferences/issue-39029.fixed +++ b/tests/ui/traits/suggest-dereferences/issue-39029.fixed diff --git a/tests/ui/traits/suggest-deferences/issue-39029.rs b/tests/ui/traits/suggest-dereferences/issue-39029.rs index 90d097105ed..90d097105ed 100644 --- a/tests/ui/traits/suggest-deferences/issue-39029.rs +++ b/tests/ui/traits/suggest-dereferences/issue-39029.rs diff --git a/tests/ui/traits/suggest-deferences/issue-39029.stderr b/tests/ui/traits/suggest-dereferences/issue-39029.stderr index 49105de3d69..49105de3d69 100644 --- a/tests/ui/traits/suggest-deferences/issue-39029.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-39029.stderr diff --git a/tests/ui/traits/suggest-deferences/issue-62530.fixed b/tests/ui/traits/suggest-dereferences/issue-62530.fixed index 406caaa007f..406caaa007f 100644 --- a/tests/ui/traits/suggest-deferences/issue-62530.fixed +++ b/tests/ui/traits/suggest-dereferences/issue-62530.fixed diff --git a/tests/ui/traits/suggest-deferences/issue-62530.rs b/tests/ui/traits/suggest-dereferences/issue-62530.rs index 53846be7306..53846be7306 100644 --- a/tests/ui/traits/suggest-deferences/issue-62530.rs +++ b/tests/ui/traits/suggest-dereferences/issue-62530.rs diff --git a/tests/ui/traits/suggest-deferences/issue-62530.stderr b/tests/ui/traits/suggest-dereferences/issue-62530.stderr index e47ae0b65af..e47ae0b65af 100644 --- a/tests/ui/traits/suggest-deferences/issue-62530.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-62530.stderr diff --git a/tests/ui/traits/suggest-deferences/multiple-0.fixed b/tests/ui/traits/suggest-dereferences/multiple-0.fixed index b7160b75c60..b7160b75c60 100644 --- a/tests/ui/traits/suggest-deferences/multiple-0.fixed +++ b/tests/ui/traits/suggest-dereferences/multiple-0.fixed diff --git a/tests/ui/traits/suggest-deferences/multiple-0.rs b/tests/ui/traits/suggest-dereferences/multiple-0.rs index 9ac55177ffa..9ac55177ffa 100644 --- a/tests/ui/traits/suggest-deferences/multiple-0.rs +++ b/tests/ui/traits/suggest-dereferences/multiple-0.rs diff --git a/tests/ui/traits/suggest-deferences/multiple-0.stderr b/tests/ui/traits/suggest-dereferences/multiple-0.stderr index 6a4d4b8d521..6a4d4b8d521 100644 --- a/tests/ui/traits/suggest-deferences/multiple-0.stderr +++ b/tests/ui/traits/suggest-dereferences/multiple-0.stderr diff --git a/tests/ui/traits/suggest-deferences/multiple-1.rs b/tests/ui/traits/suggest-dereferences/multiple-1.rs index 91c6c7924a4..91c6c7924a4 100644 --- a/tests/ui/traits/suggest-deferences/multiple-1.rs +++ b/tests/ui/traits/suggest-dereferences/multiple-1.rs diff --git a/tests/ui/traits/suggest-deferences/multiple-1.stderr b/tests/ui/traits/suggest-dereferences/multiple-1.stderr index 6e12321c233..6e12321c233 100644 --- a/tests/ui/traits/suggest-deferences/multiple-1.stderr +++ b/tests/ui/traits/suggest-dereferences/multiple-1.stderr diff --git a/tests/ui/traits/suggest-deferences/root-obligation.fixed b/tests/ui/traits/suggest-dereferences/root-obligation.fixed index 7a8433f9057..7a8433f9057 100644 --- a/tests/ui/traits/suggest-deferences/root-obligation.fixed +++ b/tests/ui/traits/suggest-dereferences/root-obligation.fixed diff --git a/tests/ui/traits/suggest-deferences/root-obligation.rs b/tests/ui/traits/suggest-dereferences/root-obligation.rs index 51bac2107e3..51bac2107e3 100644 --- a/tests/ui/traits/suggest-deferences/root-obligation.rs +++ b/tests/ui/traits/suggest-dereferences/root-obligation.rs diff --git a/tests/ui/traits/suggest-deferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index 1363fb8c47a..1363fb8c47a 100644 --- a/tests/ui/traits/suggest-deferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.fixed index ea3d1bf853a..ea3d1bf853a 100644 --- a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.fixed diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.rs index 9eda68027b2..9eda68027b2 100644 --- a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.rs diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr index ede31a2c7bc..ede31a2c7bc 100644 --- a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr |
