diff --git a/.gitignore b/.gitignore index ce797a7a8371d..089831b8013f7 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ Session.vim .project .favorites.json .settings/ +.vs/ ## Tool .valgrindrc diff --git a/Cargo.lock b/Cargo.lock index 82530c019a91c..47bf654c8f4ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4669,15 +4669,9 @@ dependencies = [ name = "rustc_smir" version = "0.0.0" dependencies = [ - "rustc_borrowck", - "rustc_driver", - "rustc_hir", - "rustc_interface", "rustc_middle", - "rustc_mir_dataflow", - "rustc_mir_transform", - "rustc_serialize", - "rustc_trait_selection", + "rustc_span", + "tracing", ] [[package]] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 7dcb03b4c786c..6fed0b660e86e 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -12,7 +12,7 @@ use crate::ptr::P; use crate::token::{self, Token}; use crate::tokenstream::*; -use rustc_data_structures::map_in_place::MapInPlace; +use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 3fdbc9715275f..8c1579baacb08 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -203,17 +203,6 @@ pub fn parse_asm_args<'a>( // Validate the order of named, positional & explicit register operands and // clobber_abi/options. We do this at the end once we have the full span // of the argument available. - if !args.options_spans.is_empty() { - diag.struct_span_err(span, "arguments are not allowed after options") - .span_labels(args.options_spans.clone(), "previous options") - .span_label(span, "argument") - .emit(); - } else if let Some((_, abi_span)) = args.clobber_abis.last() { - diag.struct_span_err(span, "arguments are not allowed after clobber_abi") - .span_label(*abi_span, "clobber_abi") - .span_label(span, "argument") - .emit(); - } if explicit_reg { if name.is_some() { diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); @@ -227,17 +216,6 @@ pub fn parse_asm_args<'a>( .emit(); continue; } - if !args.reg_args.is_empty() { - let mut err = diag.struct_span_err( - span, - "named arguments cannot follow explicit register arguments", - ); - err.span_label(span, "named argument"); - for pos in &args.reg_args { - err.span_label(args.operands[*pos].1, "explicit register argument"); - } - err.emit(); - } args.named_args.insert(name, slot); } else { if !args.named_args.is_empty() || !args.reg_args.is_empty() { @@ -478,15 +456,6 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, let full_span = span_start.to(p.prev_token.span); - if !args.options_spans.is_empty() { - let mut err = p - .sess - .span_diagnostic - .struct_span_err(full_span, "clobber_abi is not allowed after options"); - err.span_labels(args.options_spans.clone(), "options"); - return Err(err); - } - match &new_abis[..] { // should have errored above during parsing [] => unreachable!(), @@ -699,6 +668,10 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option + field("source_file", cx.expr_str(sp, location_info.0)), + // start_line: start line of the test fn identifier. + field("start_line", cx.expr_usize(sp, location_info.1)), + // start_col: start column of the test fn identifier. + field("start_col", cx.expr_usize(sp, location_info.2)), + // end_line: end line of the test fn identifier. + field("end_line", cx.expr_usize(sp, location_info.3)), + // end_col: end column of the test fn identifier. + field("end_col", cx.expr_usize(sp, location_info.4)), // compile_fail: true | false field("compile_fail", cx.expr_bool(sp, false)), // no_run: true | false @@ -364,6 +376,19 @@ pub fn expand_test_or_bench( } } +fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) { + let span = item.ident.span; + let (source_file, lo_line, lo_col, hi_line, hi_col) = + cx.sess.source_map().span_to_location_info(span); + + let file_name = match source_file { + Some(sf) => sf.name.display(FileNameDisplayPreference::Local).to_string(), + None => "no-location".to_string(), + }; + + (Symbol::intern(&file_name), lo_line, lo_col, hi_line, hi_col) +} + fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String { mod_path .iter() diff --git a/compiler/rustc_data_structures/src/map_in_place.rs b/compiler/rustc_data_structures/src/flat_map_in_place.rs similarity index 87% rename from compiler/rustc_data_structures/src/map_in_place.rs rename to compiler/rustc_data_structures/src/flat_map_in_place.rs index a0d4b7ade1f33..f58844f281794 100644 --- a/compiler/rustc_data_structures/src/map_in_place.rs +++ b/compiler/rustc_data_structures/src/flat_map_in_place.rs @@ -2,14 +2,7 @@ use smallvec::{Array, SmallVec}; use std::ptr; use thin_vec::ThinVec; -pub trait MapInPlace: Sized { - fn map_in_place(&mut self, mut f: F) - where - F: FnMut(T) -> T, - { - self.flat_map_in_place(|e| Some(f(e))) - } - +pub trait FlatMapInPlace: Sized { fn flat_map_in_place(&mut self, f: F) where F: FnMut(T) -> I, @@ -66,14 +59,14 @@ macro_rules! flat_map_in_place { }; } -impl MapInPlace for Vec { +impl FlatMapInPlace for Vec { flat_map_in_place!(); } -impl> MapInPlace for SmallVec { +impl> FlatMapInPlace for SmallVec { flat_map_in_place!(); } -impl MapInPlace for ThinVec { +impl FlatMapInPlace for ThinVec { flat_map_in_place!(); } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index a94e52fdfe604..c595bf830a3dc 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -50,6 +50,7 @@ pub fn cold_path R, R>(f: F) -> R { pub mod base_n; pub mod binary_search_util; pub mod captures; +pub mod flat_map_in_place; pub mod flock; pub mod functor; pub mod fx; @@ -57,7 +58,6 @@ pub mod graph; pub mod intern; pub mod jobserver; pub mod macros; -pub mod map_in_place; pub mod obligation_forest; pub mod owning_ref; pub mod sip128; diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 01500c2c77c90..d6cb173ba9ba0 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -12,8 +12,8 @@ use rustc_ast::tokenstream::{LazyAttrTokenStream, TokenTree}; use rustc_ast::NodeId; use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem}; use rustc_attr as attr; +use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::map_in_place::MapInPlace; use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 79d058d9c9736..4092a192e0c34 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -20,7 +20,7 @@ use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind}; use rustc_ast_pretty::pprust; -use rustc_data_structures::map_in_place::MapInPlace; +use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_feature::Features; diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl index 50e857ef60d1d..df42881644487 100644 --- a/compiler/rustc_hir_analysis/locales/en-US.ftl +++ b/compiler/rustc_hir_analysis/locales/en-US.ftl @@ -89,14 +89,14 @@ hir_analysis_missing_type_params = .note = because of the default `Self` reference, type parameters must be specified on object types hir_analysis_copy_impl_on_type_with_dtor = - the trait `Copy` may not be implemented for this type; the type has a destructor + the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors hir_analysis_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported hir_analysis_copy_impl_on_non_adt = - the trait `Copy` may not be implemented for this type + the trait `Copy` cannot be implemented for this type .label = type is not a structure or enumeration hir_analysis_const_impl_for_non_const_trait = @@ -163,3 +163,10 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function .help = cast the value to `{$cast_ty}` hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}` + +hir_analysis_invalid_union_field = + field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` + +hir_analysis_invalid_union_field_sugg = + wrap the field type in `ManuallyDrop<...>` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3449d3d439dfc..be0ae4ce2ef69 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,5 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use crate::errors::LinkageType; +use crate::errors::{self, LinkageType}; use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; @@ -114,9 +114,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b allowed_union_field(*elem, tcx, param_env) } _ => { - // Fallback case: allow `ManuallyDrop` and things that are `Copy`. + // Fallback case: allow `ManuallyDrop` and things that are `Copy`, + // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) || ty.is_copy_modulo_regions(tcx, param_env) + || ty.references_error() } } } @@ -131,26 +133,14 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b Some(Node::Field(field)) => (field.span, field.ty.span), _ => unreachable!("mir field has to correspond to hir field"), }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::InvalidUnionField { field_span, - E0740, - "unions cannot contain fields that may need dropping" - ) - .note( - "a type is guaranteed not to need dropping \ - when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type", - ) - .multipart_suggestion_verbose( - "when the type does not implement `Copy`, \ - wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped", - vec![ - (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()), - (ty_span.shrink_to_hi(), ">".into()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + sugg: errors::InvalidUnionFieldSuggestion { + lo: ty_span.shrink_to_lo(), + hi: ty_span.shrink_to_hi(), + }, + note: (), + }); return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ffb68abf978de..8294d92c9364e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -2,6 +2,7 @@ //! up data structures required by type-checking/codegen. use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{struct_span_err, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -86,7 +87,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { tcx.sess, span, E0204, - "the trait `Copy` may not be implemented for this type" + "the trait `Copy` cannot be implemented for this type" ); // We'll try to suggest constraining type parameters to fulfill the requirements of @@ -94,7 +95,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let mut errors: BTreeMap<_, Vec<_>> = Default::default(); let mut bounds = vec![]; + let mut seen_tys = FxHashSet::default(); + for (field, ty, reason) in fields { + // Only report an error once per type. + if !seen_tys.insert(ty) { + continue; + } + let field_span = tcx.def_span(field.did); err.span_label(field_span, "this field does not implement `Copy`"); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 74fec93d91e1e..dd40706f1d345 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -5,7 +5,7 @@ use rustc_errors::{ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -430,3 +430,23 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: String, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_union_field, code = "E0740")] +pub(crate) struct InvalidUnionField { + #[primary_span] + pub field_span: Span, + #[subdiagnostic] + pub sugg: InvalidUnionFieldSuggestion, + #[note] + pub note: (), +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")] +pub(crate) struct InvalidUnionFieldSuggestion { + #[suggestion_part(code = "std::mem::ManuallyDrop<")] + pub lo: Span, + #[suggestion_part(code = ">")] + pub hi: Span, +} diff --git a/compiler/rustc_hir_typeck/locales/en-US.ftl b/compiler/rustc_hir_typeck/locales/en-US.ftl index adfcbc36a4d02..2c537bf4064ae 100644 --- a/compiler/rustc_hir_typeck/locales/en-US.ftl +++ b/compiler/rustc_hir_typeck/locales/en-US.ftl @@ -4,14 +4,14 @@ hir_typeck_field_multiply_specified_in_initializer = .previous_use_label = first use of `{$ident}` hir_typeck_copy_impl_on_type_with_dtor = - the trait `Copy` may not be implemented for this type; the type has a destructor + the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors hir_typeck_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported hir_typeck_copy_impl_on_non_adt = - the trait `Copy` may not be implemented for this type + the trait `Copy` cannot be implemented for this type .label = type is not a structure or enumeration hir_typeck_trait_object_declared_with_no_traits = diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 3bef5cfcd780e..57805f7c80053 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1031,7 +1031,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .collect(); // Sort them by the name so we have a stable result. - names.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap()); + names.sort_by(|a, b| a.as_str().cmp(b.as_str())); names } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e6d6586d5eefd..4b15e48bd278e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -42,7 +42,7 @@ use rustc_trait_selection::traits::{ use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope}; use super::{CandidateSource, MethodError, NoMatchData}; use rustc_hir::intravisit::Visitor; -use std::cmp::Ordering; +use std::cmp::{self, Ordering}; use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -2527,7 +2527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !candidates.is_empty() { // Sort from most relevant to least relevant. - candidates.sort_by(|a, b| a.cmp(b).reverse()); + candidates.sort_by_key(|&info| cmp::Reverse(info)); candidates.dedup(); let param_type = match rcvr_ty.kind() { diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 678c4a0beb63e..a29403cce2f95 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -376,9 +376,18 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> { match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { + ty::Infer(ty::TyVar(mut vid)) => { + // We need to canonicalize the *root* of our ty var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_var(vid); + if root_vid != vid { + t = self.infcx.tcx.mk_ty_var(root_vid); + vid = root_vid; + } + debug!("canonical: type var found with vid {:?}", vid); match self.infcx.probe_ty_var(vid) { // `t` could be a float / int variable; canonicalize that instead. @@ -469,9 +478,18 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } } - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, mut ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { - ty::ConstKind::Infer(InferConst::Var(vid)) => { + ty::ConstKind::Infer(InferConst::Var(mut vid)) => { + // We need to canonicalize the *root* of our const var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_const_var(vid); + if root_vid != vid { + ct = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), ct.ty()); + vid = root_vid; + } + debug!("canonical: const var found with vid {:?}", vid); match self.infcx.probe_const_var(vid) { Ok(c) => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fb067e7ac2135..4a2a55573131a 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1359,6 +1359,10 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } + pub fn root_const_var(&self, var: ty::ConstVid<'tcx>) -> ty::ConstVid<'tcx> { + self.inner.borrow_mut().const_unification_table().find(var) + } + /// Where possible, replaces type/const variables in /// `value` with their final value. Note that region variables /// are unaffected. If a type/const variable has not been unified, it diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs index 02bb8dea0c01e..5c524a18454ec 100644 --- a/compiler/rustc_monomorphize/src/partitioning/merging.rs +++ b/compiler/rustc_monomorphize/src/partitioning/merging.rs @@ -24,7 +24,7 @@ pub fn merge_codegen_units<'tcx>( // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); + codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str())); // This map keeps track of what got merged into what. let mut cgu_contents: FxHashMap> = diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 524c51d88d755..7ac1c9e057e8f 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -252,7 +252,7 @@ pub fn partition<'tcx>( internalization_candidates: _, } = post_inlining; - result.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); + result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str())); result } diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs index 27f4428d306cd..c4b9fdc81c5eb 100644 --- a/compiler/rustc_parse/src/lexer/diagnostics.rs +++ b/compiler/rustc_parse/src/lexer/diagnostics.rs @@ -71,7 +71,7 @@ pub fn report_suspicious_mismatch_block( .collect(); // sort by `lo`, so the large block spans in the front - matched_spans.sort_by(|a, b| a.0.lo().cmp(&b.0.lo())); + matched_spans.sort_by_key(|(span, _)| span.lo()); // We use larger block whose identation is well to cover those inner mismatched blocks // O(N^2) here, but we are on error reporting path, so it is fine diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 206c43f6902be..6133e75a78fff 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1736,7 +1736,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. - names.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); + names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); match find_best_match_for_name( &names.iter().map(|suggestion| suggestion.candidate).collect::>(), diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index 55178250472ef..0dfee92f40434 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_span::Symbol; use rustc_target::abi::{Align, Size}; -use std::cmp::{self, Ordering}; +use std::cmp; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct VariantInfo { @@ -87,7 +87,7 @@ impl CodeStats { // Except for Generators, whose variants are already sorted according to // their yield points in `variant_info_for_generator`. if kind != DataTypeKind::Generator { - variants.sort_by(|info1, info2| info2.size.cmp(&info1.size)); + variants.sort_by_key(|info| cmp::Reverse(info.size)); } let info = TypeSizeInfo { kind, @@ -107,13 +107,7 @@ impl CodeStats { // Primary sort: large-to-small. // Secondary sort: description (dictionary order) - sorted.sort_by(|info1, info2| { - // (reversing cmp order to get large-to-small ordering) - match info2.overall_size.cmp(&info1.overall_size) { - Ordering::Equal => info1.type_description.cmp(&info2.type_description), - other => other, - } - }); + sorted.sort_by_key(|info| (cmp::Reverse(info.overall_size), &info.type_description)); for info in sorted { let TypeSizeInfo { type_description, overall_size, align, kind, variants, .. } = info; diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 5e0d1f369a6a2..fb97ee5bebe6e 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,25 +4,12 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_borrowck = { path = "../rustc_borrowck", optional = true } -rustc_driver = { path = "../rustc_driver", optional = true } -rustc_hir = { path = "../rustc_hir", optional = true } -rustc_interface = { path = "../rustc_interface", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } -rustc_mir_dataflow = { path = "../rustc_mir_dataflow", optional = true } -rustc_mir_transform = { path = "../rustc_mir_transform", optional = true } -rustc_serialize = { path = "../rustc_serialize", optional = true } -rustc_trait_selection = { path = "../rustc_trait_selection", optional = true } +rustc_span = { path = "../rustc_span", optional = true } +tracing = "0.1" [features] default = [ - "rustc_borrowck", - "rustc_driver", - "rustc_hir", - "rustc_interface", "rustc_middle", - "rustc_mir_dataflow", - "rustc_mir_transform", - "rustc_serialize", - "rustc_trait_selection", + "rustc_span", ] diff --git a/compiler/rustc_smir/README.md b/compiler/rustc_smir/README.md index ae49098dd0ce6..31dee955f491f 100644 --- a/compiler/rustc_smir/README.md +++ b/compiler/rustc_smir/README.md @@ -73,3 +73,40 @@ git subtree pull --prefix=compiler/rustc_smir https://github.com/rust-lang/proje Note: only ever sync to rustc from the project-stable-mir's `smir` branch. Do not sync with your own forks. Then open a PR against rustc just like a regular PR. + +## Stable MIR Design + +The stable-mir will follow a similar approach to proc-macro2. It’s +implementation will eventually be broken down into two main crates: + +- `stable_mir`: Public crate, to be published on crates.io, which will contain +the stable data structure as well as proxy APIs to make calls to the +compiler. +- `rustc_smir`: The compiler crate that will translate from internal MIR to +SMIR. This crate will also implement APIs that will be invoked by +stable-mir to query the compiler for more information. + +This will help tools to communicate with the rust compiler via stable APIs. Tools will depend on +`stable_mir` crate, which will invoke the compiler using APIs defined in `rustc_smir`. I.e.: + +``` + ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ + │ External Tool ┌──────────┐ │ │ ┌──────────┐ Rust Compiler │ + │ │ │ │ │ │ │ │ + │ │stable_mir| │ │ │rustc_smir│ │ + │ │ │ ├──────────►| │ │ │ + │ │ │ │◄──────────┤ │ │ │ + │ │ │ │ │ │ │ │ + │ │ │ │ │ │ │ │ + │ └──────────┘ │ │ └──────────┘ │ + └──────────────────────────────────┘ └──────────────────────────────────┘ +``` + +More details can be found here: +https://hackmd.io/XhnYHKKuR6-LChhobvlT-g?view + +For now, the code for these two crates are in separate modules of this crate. +The modules have the same name for simplicity. We also have a third module, +`rustc_internal` which will expose APIs and definitions that allow users to +gather information from internal MIR constructs that haven't been exposed in +the `stable_mir` module. diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml index 7b696fc1f5cec..157dfd620ee1b 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/rustc_smir/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-06-01" +channel = "nightly-2023-02-28" components = [ "rustfmt", "rustc-dev" ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 3e93c6bba977f..54d474db038e9 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -11,9 +11,9 @@ test(attr(allow(unused_variables), deny(warnings))) )] #![cfg_attr(not(feature = "default"), feature(rustc_private))] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] -pub mod mir; +pub mod rustc_internal; +pub mod stable_mir; -pub mod very_unstable; +// Make this module private for now since external users should not call these directly. +mod rustc_smir; diff --git a/compiler/rustc_smir/src/mir.rs b/compiler/rustc_smir/src/mir.rs deleted file mode 100644 index 887e657293066..0000000000000 --- a/compiler/rustc_smir/src/mir.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub use crate::very_unstable::hir::ImplicitSelfKind; -pub use crate::very_unstable::middle::mir::{ - visit::MutVisitor, AggregateKind, AssertKind, BasicBlock, BasicBlockData, BinOp, BindingForm, - BlockTailInfo, Body, BorrowKind, CastKind, ClearCrossCrate, Constant, ConstantKind, - CopyNonOverlapping, Coverage, FakeReadCause, Field, GeneratorInfo, InlineAsmOperand, Local, - LocalDecl, LocalInfo, LocalKind, Location, MirPhase, MirSource, NullOp, Operand, Place, - PlaceRef, ProjectionElem, ProjectionKind, Promoted, RetagKind, Rvalue, Safety, SourceInfo, - SourceScope, SourceScopeData, SourceScopeLocalData, Statement, StatementKind, UnOp, - UserTypeProjection, UserTypeProjections, VarBindingForm, VarDebugInfo, VarDebugInfoContents, -}; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs new file mode 100644 index 0000000000000..3eaff9c051f1c --- /dev/null +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -0,0 +1,15 @@ +//! Module that implements the bridge between Stable MIR and internal compiler MIR. +//! +//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs +//! until stable MIR is complete. + +use crate::stable_mir; +pub use rustc_span::def_id::{CrateNum, DefId}; + +pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId { + item.0 +} + +pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { + item.id.into() +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs new file mode 100644 index 0000000000000..d956f0ac80213 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -0,0 +1,48 @@ +//! Module that implements what will become the rustc side of Stable MIR. +//! +//! This module is responsible for building Stable MIR components from internal components. +//! +//! This module is not intended to be invoked directly by users. It will eventually +//! become the public API of rustc that will be invoked by the `stable_mir` crate. +//! +//! For now, we are developing everything inside `rustc`, thus, we keep this module private. + +use crate::stable_mir::{self}; +use rustc_middle::ty::{tls::with, TyCtxt}; +use rustc_span::def_id::{CrateNum, LOCAL_CRATE}; +use tracing::debug; + +/// Get information about the local crate. +pub fn local_crate() -> stable_mir::Crate { + with(|tcx| smir_crate(tcx, LOCAL_CRATE)) +} + +/// Retrieve a list of all external crates. +pub fn external_crates() -> Vec { + with(|tcx| tcx.crates(()).iter().map(|crate_num| smir_crate(tcx, *crate_num)).collect()) +} + +/// Find a crate with the given name. +pub fn find_crate(name: &str) -> Option { + with(|tcx| { + [LOCAL_CRATE].iter().chain(tcx.crates(()).iter()).find_map(|crate_num| { + let crate_name = tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tcx, *crate_num)) + }) + }) +} + +/// Retrieve all items of the local crate that have a MIR associated with them. +pub fn all_local_items() -> stable_mir::CrateItems { + with(|tcx| { + tcx.mir_keys(()).iter().map(|item| stable_mir::CrateItem(item.to_def_id())).collect() + }) +} + +/// Build a stable mir crate from a given crate number. +fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { + let crate_name = tcx.crate_name(crate_num).to_string(); + let is_local = crate_num == LOCAL_CRATE; + debug!(?crate_name, ?crate_num, "smir_crate"); + stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } +} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs new file mode 100644 index 0000000000000..cbf52e691fb47 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -0,0 +1,60 @@ +//! Module that implements the public interface to the Stable MIR. +//! +//! This module shall contain all type definitions and APIs that we expect 3P tools to invoke to +//! interact with the compiler. +//! +//! The goal is to eventually move this module to its own crate which shall be published on +//! [crates.io](https://crates.io). +//! +//! ## Note: +//! +//! There shouldn't be any direct references to internal compiler constructs in this module. +//! If you need an internal construct, consider using `rustc_internal` or `rustc_smir`. + +use crate::rustc_internal; + +/// Use String for now but we should replace it. +pub type Symbol = String; + +/// The number that identifies a crate. +pub type CrateNum = usize; + +/// A unique identification number for each item accessible for the current compilation unit. +pub type DefId = usize; + +/// A list of crate items. +pub type CrateItems = Vec; + +/// Holds information about a crate. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Crate { + pub(crate) id: CrateNum, + pub name: Symbol, + pub is_local: bool, +} + +/// Holds information about an item in the crate. +/// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to +/// use this item. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CrateItem(pub(crate) rustc_internal::DefId); + +/// Access to the local crate. +pub fn local_crate() -> Crate { + crate::rustc_smir::local_crate() +} + +/// Try to find a crate with the given name. +pub fn find_crate(name: &str) -> Option { + crate::rustc_smir::find_crate(name) +} + +/// Try to find a crate with the given name. +pub fn external_crates() -> Vec { + crate::rustc_smir::external_crates() +} + +/// Retrieve all items in the local crate that have a MIR associated with them. +pub fn all_local_items() -> CrateItems { + crate::rustc_smir::all_local_items() +} diff --git a/compiler/rustc_smir/src/very_unstable.rs b/compiler/rustc_smir/src/very_unstable.rs deleted file mode 100644 index 12ba133dbb169..0000000000000 --- a/compiler/rustc_smir/src/very_unstable.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! This module reexports various crates and modules from unstable rustc APIs. -//! Add anything you need here and it will get slowly transferred to a stable API. -//! Only use rustc_smir in your dependencies and use the reexports here instead of -//! directly referring to the unstable crates. - -macro_rules! crates { - ($($rustc_name:ident -> $name:ident,)*) => { - $( - #[cfg(not(feature = "default"))] - pub extern crate $rustc_name as $name; - #[cfg(feature = "default")] - pub use $rustc_name as $name; - )* - } -} - -crates! { - rustc_borrowck -> borrowck, - rustc_driver -> driver, - rustc_hir -> hir, - rustc_interface -> interface, - rustc_middle -> middle, - rustc_mir_dataflow -> dataflow, - rustc_mir_transform -> transform, - rustc_serialize -> serialize, - rustc_trait_selection -> trait_selection, -} diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 2e339a9d2d2b0..cca9359141c68 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -443,25 +443,36 @@ impl SourceMap { sp: Span, filename_display_pref: FileNameDisplayPreference, ) -> String { - if self.files.borrow().source_files.is_empty() || sp.is_dummy() { - return "no-location".to_string(); - } + let (source_file, lo_line, lo_col, hi_line, hi_col) = self.span_to_location_info(sp); + + let file_name = match source_file { + Some(sf) => sf.name.display(filename_display_pref).to_string(), + None => return "no-location".to_string(), + }; - let lo = self.lookup_char_pos(sp.lo()); - let hi = self.lookup_char_pos(sp.hi()); format!( - "{}:{}:{}{}", - lo.file.name.display(filename_display_pref), - lo.line, - lo.col.to_usize() + 1, + "{file_name}:{lo_line}:{lo_col}{}", if let FileNameDisplayPreference::Short = filename_display_pref { String::new() } else { - format!(": {}:{}", hi.line, hi.col.to_usize() + 1) + format!(": {hi_line}:{hi_col}") } ) } + pub fn span_to_location_info( + &self, + sp: Span, + ) -> (Option>, usize, usize, usize, usize) { + if self.files.borrow().source_files.is_empty() || sp.is_dummy() { + return (None, 0, 0, 0, 0); + } + + let lo = self.lookup_char_pos(sp.lo()); + let hi = self.lookup_char_pos(sp.hi()); + (Some(lo.file), lo.line, lo.col.to_usize() + 1, hi.line, hi.col.to_usize() + 1) + } + /// Format the span location suitable for embedding in build artifacts pub fn span_to_embeddable_string(&self, sp: Span) -> String { self.span_to_string(sp, FileNameDisplayPreference::Remapped) diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs index c048d4a2aad76..981a8f45e4542 100644 --- a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs @@ -261,12 +261,23 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { self.interner().mk_re_late_bound(self.binder_index, br) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> { let kind = match *t.kind() { - ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) { - Ok(t) => return self.fold_ty(t), - Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), - }, + ty::Infer(ty::TyVar(mut vid)) => { + // We need to canonicalize the *root* of our ty var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_var(vid); + if root_vid != vid { + t = self.infcx.tcx.mk_ty_var(root_vid); + vid = root_vid; + } + + match self.infcx.probe_ty_var(vid) { + Ok(t) => return self.fold_ty(t), + Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), + } + } ty::Infer(ty::IntVar(_)) => { let nt = self.infcx.shallow_resolve(t); if nt != t { @@ -338,13 +349,23 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { self.interner().mk_bound(self.binder_index, bt) } - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> { let kind = match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid) - { - Ok(c) => return self.fold_const(c), - Err(universe) => CanonicalVarKind::Const(universe, c.ty()), - }, + ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => { + // We need to canonicalize the *root* of our const var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_const_var(vid); + if root_vid != vid { + c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty()); + vid = root_vid; + } + + match self.infcx.probe_const_var(vid) { + Ok(c) => return self.fold_const(c), + Err(universe) => CanonicalVarKind::Const(universe, c.ty()), + } + } ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => { bug!("fresh var during canonicalization: {c:?}") } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 57b6a45273718..43fd415e871e1 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -238,6 +238,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { && has_changed && !self.in_projection_eq_hack && !self.search_graph.in_cycle() + && false { let (_orig_values, canonical_goal) = self.canonicalize_goal(goal); let canonical_response = diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index b94346b09560a..336db4fee6ced 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -87,7 +87,12 @@ pub fn type_allowed_to_implement_copy<'tcx>( }; let ty = ocx.normalize(&normalization_cause, param_env, unnormalized_ty); let normalization_errors = ocx.select_where_possible(); - if !normalization_errors.is_empty() { + + // NOTE: The post-normalization type may also reference errors, + // such as when we project to a missing type or we have a mismatch + // between expected and found const-generic types. Don't report an + // additional copy error here, since it's not typically useful. + if !normalization_errors.is_empty() || ty.references_error() { tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking Copy implementation")); continue; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cd3f3c114ba1e..48c3b3601b4d3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1083,7 +1083,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested_result = EvaluationResult::EvaluatedToOk; for obligation in nested_obligations { nested_result = cmp::max( - this.evaluate_predicate_recursively(stack.list(), obligation)?, + this.evaluate_predicate_recursively(previous_stack, obligation)?, nested_result, ); } @@ -1092,7 +1092,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation = obligation.with(this.tcx(), predicate); result = cmp::max( nested_result, - this.evaluate_trait_predicate_recursively(stack.list(), obligation)?, + this.evaluate_trait_predicate_recursively(previous_stack, obligation)?, ); } } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 520ae0edb09c2..427146941ade8 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -324,7 +324,7 @@ pub trait StructuralEq { /// attempt to derive a `Copy` implementation, we'll get an error: /// /// ```text -/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` +/// the trait `Copy` cannot be implemented for this type; field `points` does not implement `Copy` /// ``` /// /// Shared references (`&T`) are also `Copy`, so a type can be `Copy`, even when it holds diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 1ee68c8540bcc..7eee4ca236190 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -41,6 +41,46 @@ impl Write for OutputLocation { } } +pub struct ConsoleTestDiscoveryState { + pub log_out: Option, + pub tests: usize, + pub benchmarks: usize, + pub ignored: usize, + pub options: Options, +} + +impl ConsoleTestDiscoveryState { + pub fn new(opts: &TestOpts) -> io::Result { + let log_out = match opts.logfile { + Some(ref path) => Some(File::create(path)?), + None => None, + }; + + Ok(ConsoleTestDiscoveryState { + log_out, + tests: 0, + benchmarks: 0, + ignored: 0, + options: opts.options, + }) + } + + pub fn write_log(&mut self, msg: F) -> io::Result<()> + where + S: AsRef, + F: FnOnce() -> S, + { + match self.log_out { + None => Ok(()), + Some(ref mut o) => { + let msg = msg(); + let msg = msg.as_ref(); + o.write_all(msg.as_bytes()) + } + } + } +} + pub struct ConsoleTestState { pub log_out: Option, pub total: usize, @@ -138,53 +178,44 @@ impl ConsoleTestState { // List the tests to console, and optionally to logfile. Filters are honored. pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Result<()> { - let mut output = match term::stdout() { + let output = match term::stdout() { None => OutputLocation::Raw(io::stdout().lock()), Some(t) => OutputLocation::Pretty(t), }; - let quiet = opts.format == OutputFormat::Terse; - let mut st = ConsoleTestState::new(opts)?; - - let mut ntest = 0; - let mut nbench = 0; + let mut out: Box = match opts.format { + OutputFormat::Pretty | OutputFormat::Junit => { + Box::new(PrettyFormatter::new(output, false, 0, false, None)) + } + OutputFormat::Terse => Box::new(TerseFormatter::new(output, false, 0, false)), + OutputFormat::Json => Box::new(JsonFormatter::new(output)), + }; + let mut st = ConsoleTestDiscoveryState::new(opts)?; + out.write_discovery_start()?; for test in filter_tests(opts, tests).into_iter() { use crate::TestFn::*; - let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test; + let TestDescAndFn { desc, testfn } = test; let fntype = match testfn { StaticTestFn(..) | DynTestFn(..) => { - ntest += 1; + st.tests += 1; "test" } StaticBenchFn(..) | DynBenchFn(..) => { - nbench += 1; + st.benchmarks += 1; "benchmark" } }; - writeln!(output, "{name}: {fntype}")?; - st.write_log(|| format!("{fntype} {name}\n"))?; - } + st.ignored += if desc.ignore { 1 } else { 0 }; - fn plural(count: u32, s: &str) -> String { - match count { - 1 => format!("1 {s}"), - n => format!("{n} {s}s"), - } + out.write_test_discovered(&desc, fntype)?; + st.write_log(|| format!("{fntype} {}\n", desc.name))?; } - if !quiet { - if ntest != 0 || nbench != 0 { - writeln!(output)?; - } - - writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?; - } - - Ok(()) + out.write_discovery_finish(&st) } // Updates `ConsoleTestState` depending on result of the test execution. diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 95d2faf25060f..40976ec5e1c8b 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, io, io::prelude::Write}; use super::OutputFormatter; use crate::{ - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, test_result::TestResult, time, types::TestDesc, @@ -60,6 +60,56 @@ impl JsonFormatter { } impl OutputFormatter for JsonFormatter { + fn write_discovery_start(&mut self) -> io::Result<()> { + self.writeln_message(&format!(r#"{{ "type": "suite", "event": "discovery" }}"#)) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + let TestDesc { + name, + ignore, + ignore_message, + #[cfg(not(bootstrap))] + source_file, + #[cfg(not(bootstrap))] + start_line, + #[cfg(not(bootstrap))] + start_col, + #[cfg(not(bootstrap))] + end_line, + #[cfg(not(bootstrap))] + end_col, + .. + } = desc; + + #[cfg(bootstrap)] + let source_file = ""; + #[cfg(bootstrap)] + let start_line = 0; + #[cfg(bootstrap)] + let start_col = 0; + #[cfg(bootstrap)] + let end_line = 0; + #[cfg(bootstrap)] + let end_col = 0; + + self.writeln_message(&format!( + r#"{{ "type": "{test_type}", "event": "discovered", "name": "{}", "ignore": {ignore}, "ignore_message": "{}", "source_path": "{}", "start_line": {start_line}, "start_col": {start_col}, "end_line": {end_line}, "end_col": {end_col} }}"#, + EscapedString(name.as_slice()), + ignore_message.unwrap_or(""), + EscapedString(source_file), + )) + } + + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()> { + let ConsoleTestDiscoveryState { tests, benchmarks, ignored, .. } = state; + + let total = tests + benchmarks; + self.writeln_message(&format!( + r#"{{ "type": "suite", "event": "completed", "tests": {tests}, "benchmarks": {benchmarks}, "total": {total}, "ignored": {ignored} }}"# + )) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { let shuffle_seed_json = if let Some(shuffle_seed) = shuffle_seed { format!(r#", "shuffle_seed": {shuffle_seed}"#) diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 7a40ce33cb741..2e07ce3c09923 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -3,7 +3,7 @@ use std::time::Duration; use super::OutputFormatter; use crate::{ - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, test_result::TestResult, time, types::{TestDesc, TestType}, @@ -27,6 +27,18 @@ impl JunitFormatter { } impl OutputFormatter for JunitFormatter { + fn write_discovery_start(&mut self) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + + fn write_test_discovered(&mut self, _desc: &TestDesc, _test_type: &str) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + + fn write_discovery_finish(&mut self, _state: &ConsoleTestDiscoveryState) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!")) + } + fn write_run_start( &mut self, _test_count: usize, diff --git a/library/test/src/formatters/mod.rs b/library/test/src/formatters/mod.rs index cb67b6491a392..bc6ffebc1d3b2 100644 --- a/library/test/src/formatters/mod.rs +++ b/library/test/src/formatters/mod.rs @@ -1,7 +1,7 @@ use std::{io, io::prelude::Write}; use crate::{ - console::ConsoleTestState, + console::{ConsoleTestDiscoveryState, ConsoleTestState}, test_result::TestResult, time, types::{TestDesc, TestName}, @@ -18,6 +18,10 @@ pub(crate) use self::pretty::PrettyFormatter; pub(crate) use self::terse::TerseFormatter; pub(crate) trait OutputFormatter { + fn write_discovery_start(&mut self) -> io::Result<()>; + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()>; + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()>; + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()>; fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>; fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>; diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 247778e515f0d..22654a3400b44 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -3,7 +3,7 @@ use std::{io, io::prelude::Write}; use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, term, test_result::TestResult, time, @@ -181,6 +181,33 @@ impl PrettyFormatter { } impl OutputFormatter for PrettyFormatter { + fn write_discovery_start(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + self.write_plain(format!("{}: {test_type}\n", desc.name)) + } + + fn write_discovery_finish(&mut self, state: &ConsoleTestDiscoveryState) -> io::Result<()> { + fn plural(count: usize, s: &str) -> String { + match count { + 1 => format!("1 {s}"), + n => format!("{n} {s}s"), + } + } + + if state.tests != 0 || state.benchmarks != 0 { + self.write_plain("\n")?; + } + + self.write_plain(format!( + "{}, {}\n", + plural(state.tests, "test"), + plural(state.benchmarks, "benchmark") + )) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { let noun = if test_count != 1 { "tests" } else { "test" }; let shuffle_seed_msg = if let Some(shuffle_seed) = shuffle_seed { diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index a431acfbc2753..2931ca6ead0ac 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -3,7 +3,7 @@ use std::{io, io::prelude::Write}; use super::OutputFormatter; use crate::{ bench::fmt_bench_samples, - console::{ConsoleTestState, OutputLocation}, + console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation}, term, test_result::TestResult, time, @@ -167,6 +167,18 @@ impl TerseFormatter { } impl OutputFormatter for TerseFormatter { + fn write_discovery_start(&mut self) -> io::Result<()> { + Ok(()) + } + + fn write_test_discovered(&mut self, desc: &TestDesc, test_type: &str) -> io::Result<()> { + self.write_plain(format!("{}: {test_type}\n", desc.name)) + } + + fn write_discovery_finish(&mut self, _state: &ConsoleTestDiscoveryState) -> io::Result<()> { + Ok(()) + } + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { self.total_test_count = test_count; let noun = if test_count != 1 { "tests" } else { "test" }; diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 44776fb0a316d..5ffdbf73fbf93 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -63,6 +63,16 @@ fn one_ignored_one_unignored_test() -> Vec { name: StaticTestName("1"), ignore: true, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -75,6 +85,16 @@ fn one_ignored_one_unignored_test() -> Vec { name: StaticTestName("2"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -95,6 +115,16 @@ pub fn do_not_run_ignored_tests() { name: StaticTestName("whatever"), ignore: true, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -118,6 +148,16 @@ pub fn ignored_tests_result_in_ignored() { name: StaticTestName("whatever"), ignore: true, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -143,6 +183,16 @@ fn test_should_panic() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::Yes, compile_fail: false, no_run: false, @@ -168,6 +218,16 @@ fn test_should_panic_good_message() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::YesWithMessage("error message"), compile_fail: false, no_run: false, @@ -198,6 +258,16 @@ fn test_should_panic_bad_message() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, no_run: false, @@ -232,6 +302,16 @@ fn test_should_panic_non_string_message_type() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, no_run: false, @@ -260,6 +340,16 @@ fn test_should_panic_but_succeeds() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic, compile_fail: false, no_run: false, @@ -288,6 +378,16 @@ fn report_time_test_template(report_time: bool) -> Option { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -325,6 +425,16 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -364,6 +474,16 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -476,6 +596,16 @@ pub fn exclude_should_panic_option() { name: StaticTestName("3"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::Yes, compile_fail: false, no_run: false, @@ -500,6 +630,16 @@ pub fn exact_filter_match() { name: StaticTestName(name), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -591,6 +731,16 @@ fn sample_tests() -> Vec { name: DynTestName((*name).clone()), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -720,6 +870,16 @@ pub fn test_bench_no_iter() { name: StaticTestName("f"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -743,6 +903,16 @@ pub fn test_bench_iter() { name: StaticTestName("f"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -759,6 +929,16 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("a"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -769,6 +949,16 @@ fn should_sort_failures_before_printing_them() { name: StaticTestName("b"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, @@ -816,6 +1006,16 @@ fn test_dyn_bench_returning_err_fails_when_run_as_test() { name: StaticTestName("whatever"), ignore: false, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic: ShouldPanic::No, compile_fail: false, no_run: false, diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 6f2e033095a37..8d4e204c8ac12 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -119,6 +119,16 @@ pub struct TestDesc { pub name: TestName, pub ignore: bool, pub ignore_message: Option<&'static str>, + #[cfg(not(bootstrap))] + pub source_file: &'static str, + #[cfg(not(bootstrap))] + pub start_line: usize, + #[cfg(not(bootstrap))] + pub start_col: usize, + #[cfg(not(bootstrap))] + pub end_line: usize, + #[cfg(not(bootstrap))] + pub end_col: usize, pub should_panic: options::ShouldPanic, pub compile_fail: bool, pub no_run: bool, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 9cf84acc79f8d..aaa83ecce4817 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1057,6 +1057,16 @@ impl Tester for Collector { Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, ignore_message: None, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, // compiler failures are test failures should_panic: test::ShouldPanic::No, compile_fail: config.compile_fail, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index d9b39927ca4bc..22a0b1d13be16 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1047,6 +1047,16 @@ pub fn make_test_description( name, ignore, ignore_message, + #[cfg(not(bootstrap))] + source_file: "", + #[cfg(not(bootstrap))] + start_line: 0, + #[cfg(not(bootstrap))] + start_col: 0, + #[cfg(not(bootstrap))] + end_line: 0, + #[cfg(not(bootstrap))] + end_col: 0, should_panic, compile_fail: false, no_run: false, diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 15dcd4ed97df4..b58bad35104ec 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -18,6 +18,11 @@ name: test::StaticTestName("m_test"), ignore: false, ignore_message: ::core::option::Option::None, + source_file: "/checkout/tests/pretty/tests-are-sorted.rs", + start_line: 7usize, + start_col: 4usize, + end_line: 7usize, + end_col: 10usize, compile_fail: false, no_run: false, should_panic: test::ShouldPanic::No, @@ -34,8 +39,13 @@ test::TestDescAndFn { desc: test::TestDesc { name: test::StaticTestName("z_test"), - ignore: false, - ignore_message: ::core::option::Option::None, + ignore: true, + ignore_message: ::core::option::Option::Some("not yet implemented"), + source_file: "/checkout/tests/pretty/tests-are-sorted.rs", + start_line: 11usize, + start_col: 4usize, + end_line: 11usize, + end_col: 10usize, compile_fail: false, no_run: false, should_panic: test::ShouldPanic::No, @@ -43,6 +53,7 @@ }, testfn: test::StaticTestFn(|| test::assert_test_result(z_test())), }; +#[ignore = "not yet implemented"] fn z_test() {} extern crate test; @@ -54,6 +65,11 @@ name: test::StaticTestName("a_test"), ignore: false, ignore_message: ::core::option::Option::None, + source_file: "/checkout/tests/pretty/tests-are-sorted.rs", + start_line: 14usize, + start_col: 4usize, + end_line: 14usize, + end_col: 10usize, compile_fail: false, no_run: false, should_panic: test::ShouldPanic::No, diff --git a/tests/pretty/tests-are-sorted.rs b/tests/pretty/tests-are-sorted.rs index 1f737d5471930..0899b820f269f 100644 --- a/tests/pretty/tests-are-sorted.rs +++ b/tests/pretty/tests-are-sorted.rs @@ -7,6 +7,7 @@ fn m_test() {} #[test] +#[ignore = "not yet implemented"] fn z_test() {} #[test] diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs new file mode 100644 index 0000000000000..4458ab0162e95 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -0,0 +1,104 @@ +// run-pass +// Test that users are able to use stable mir APIs to retrieve information of the current crate + +// ignore-stage-1 +// ignore-cross-compile +// ignore-remote + +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate rustc_smir; + +use rustc_driver::{Callbacks, Compilation, RunCompiler}; +use rustc_hir::def::DefKind; +use rustc_interface::{interface, Queries}; +use rustc_middle::ty::TyCtxt; +use rustc_smir::{rustc_internal, stable_mir}; +use std::io::Write; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(tcx: TyCtxt<'_>) { + // Get the local crate using stable_mir API. + let local = stable_mir::local_crate(); + assert_eq!(&local.name, CRATE_NAME); + + // Find items in the local crate. + let items = stable_mir::all_local_items(); + assert!(has_item(tcx, &items, (DefKind::Fn, "foo_bar"))); + assert!(has_item(tcx, &items, (DefKind::Fn, "foo::bar"))); + + // Find the `std` crate. + assert!(stable_mir::find_crate("std").is_some()); +} + +// Use internal API to find a function in a crate. +fn has_item(tcx: TyCtxt, items: &stable_mir::CrateItems, item: (DefKind, &str)) -> bool { + items.iter().any(|crate_item| { + let def_id = rustc_internal::item_def_id(crate_item); + tcx.def_kind(def_id) == item.0 && tcx.def_path_str(def_id) == item.1 + }) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// It will invoke the compiler using a custom Callback implementation, which will +/// invoke Stable MIR APIs after the compiler has finished its analysis. +fn main() { + let path = "input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + rustc_driver::catch_fatal_errors(|| { + RunCompiler::new(&args, &mut SMirCalls {}).run().unwrap(); + }) + .unwrap(); +} + +struct SMirCalls {} + +impl Callbacks for SMirCalls { + /// Called after analysis. Return value instructs the compiler whether to + /// continue the compilation afterwards (defaults to `Compilation::Continue`) + fn after_analysis<'tcx>( + &mut self, + _compiler: &interface::Compiler, + queries: &'tcx Queries<'tcx>, + ) -> Compilation { + queries.global_ctxt().unwrap().enter(|tcx| { + test_stable_mir(tcx); + }); + // No need to keep going. + Compilation::Stop + } +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + mod foo {{ + pub fn bar(i: i32) -> i64 {{ + i as i64 + }} + }} + + pub fn foo_bar(x: i32, y: i32) -> i64 {{ + let x_64 = foo::bar(x); + let y_64 = foo::bar(y); + x_64.wrapping_add(y_64) + }}"# + )?; + Ok(()) +} diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs index cbc93cd3f7530..9b8170840bb07 100644 --- a/tests/ui/asm/aarch64/parse-error.rs +++ b/tests/ui/asm/aarch64/parse-error.rs @@ -37,8 +37,7 @@ fn main() { asm!("", options(nomem, foo)); //~^ ERROR expected one of asm!("{}", options(), const foo); - //~^ ERROR arguments are not allowed after options - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("", clobber_abi(foo)); //~^ ERROR expected string literal asm!("", clobber_abi("C" foo)); @@ -46,12 +45,10 @@ fn main() { asm!("", clobber_abi("C", foo)); //~^ ERROR expected string literal asm!("{}", clobber_abi("C"), const foo); - //~^ ERROR arguments are not allowed after clobber_abi - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("", options(), clobber_abi("C")); - //~^ ERROR clobber_abi is not allowed after options asm!("{}", options(), clobber_abi("C"), const foo); - //~^ ERROR clobber_abi is not allowed after options + //~^ ERROR attempt to use a non-constant value in a constant asm!("{a}", a = const foo, a = const bar); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used @@ -60,11 +57,9 @@ fn main() { asm!("", a = in("x0") foo); //~^ ERROR explicit register arguments cannot have names asm!("{a}", in("x0") foo, a = const bar); - //~^ ERROR named arguments cannot follow explicit register arguments - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("{a}", in("x0") foo, a = const bar); - //~^ ERROR named arguments cannot follow explicit register arguments - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("{1}", in("x0") foo, const bar); //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments //~^^ ERROR attempt to use a non-constant value in a constant @@ -106,7 +101,6 @@ global_asm!("", options(nomem FOO)); global_asm!("", options(nomem, FOO)); //~^ ERROR expected one of global_asm!("{}", options(), const FOO); -//~^ ERROR arguments are not allowed after options global_asm!("", clobber_abi(FOO)); //~^ ERROR expected string literal global_asm!("", clobber_abi("C" FOO)); @@ -114,12 +108,11 @@ global_asm!("", clobber_abi("C" FOO)); global_asm!("", clobber_abi("C", FOO)); //~^ ERROR expected string literal global_asm!("{}", clobber_abi("C"), const FOO); -//~^ ERROR arguments are not allowed after clobber_abi -//~^^ ERROR `clobber_abi` cannot be used with `global_asm!` +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("", options(), clobber_abi("C")); -//~^ ERROR clobber_abi is not allowed after options +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("{}", options(), clobber_abi("C"), const FOO); -//~^ ERROR clobber_abi is not allowed after options +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("{a}", a = const FOO, a = const BAR); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr index 804966b06ba7d..46984a1fe1ca0 100644 --- a/tests/ui/asm/aarch64/parse-error.stderr +++ b/tests/ui/asm/aarch64/parse-error.stderr @@ -82,58 +82,26 @@ error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `no LL | asm!("", options(nomem, foo)); | ^^^ expected one of 10 possible tokens -error: arguments are not allowed after options - --> $DIR/parse-error.rs:39:31 - | -LL | asm!("{}", options(), const foo); - | --------- ^^^^^^^^^ argument - | | - | previous options - error: expected string literal - --> $DIR/parse-error.rs:42:30 + --> $DIR/parse-error.rs:41:30 | LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:44:34 + --> $DIR/parse-error.rs:43:34 | LL | asm!("", clobber_abi("C" foo)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:46:35 + --> $DIR/parse-error.rs:45:35 | LL | asm!("", clobber_abi("C", foo)); | ^^^ not a string literal -error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:48:38 - | -LL | asm!("{}", clobber_abi("C"), const foo); - | ---------------- ^^^^^^^^^ argument - | | - | clobber_abi - -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:51:29 - | -LL | asm!("", options(), clobber_abi("C")); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options - -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:53:31 - | -LL | asm!("{}", options(), clobber_abi("C"), const foo); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options - error: duplicate argument named `a` - --> $DIR/parse-error.rs:55:36 + --> $DIR/parse-error.rs:52:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -141,7 +109,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:55:36 + --> $DIR/parse-error.rs:52:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -149,29 +117,13 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:60:18 + --> $DIR/parse-error.rs:57:18 | LL | asm!("", a = in("x0") foo); | ^^^^^^^^^^^^^^^^ -error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:62:35 - | -LL | asm!("{a}", in("x0") foo, a = const bar); - | ------------ ^^^^^^^^^^^^^ named argument - | | - | explicit register argument - -error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:65:35 - | -LL | asm!("{a}", in("x0") foo, a = const bar); - | ------------ ^^^^^^^^^^^^^ named argument - | | - | explicit register argument - error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:68:35 + --> $DIR/parse-error.rs:63:35 | LL | asm!("{1}", in("x0") foo, const bar); | ------------ ^^^^^^^^^ positional argument @@ -179,19 +131,19 @@ LL | asm!("{1}", in("x0") foo, const bar); | explicit register argument error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:71:29 + --> $DIR/parse-error.rs:66:29 | LL | asm!("", options(), ""); | ^^ expected one of 9 possible tokens error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:73:33 + --> $DIR/parse-error.rs:68:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 9 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:75:14 + --> $DIR/parse-error.rs:70:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -199,7 +151,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:77:21 + --> $DIR/parse-error.rs:72:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ @@ -207,135 +159,115 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: _ cannot be used for input operands - --> $DIR/parse-error.rs:79:28 + --> $DIR/parse-error.rs:74:28 | LL | asm!("{}", in(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:81:31 + --> $DIR/parse-error.rs:76:31 | LL | asm!("{}", inout(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:83:35 + --> $DIR/parse-error.rs:78:35 | LL | asm!("{}", inlateout(reg) _); | ^ error: requires at least a template string argument - --> $DIR/parse-error.rs:90:1 + --> $DIR/parse-error.rs:85:1 | LL | global_asm!(); | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:92:13 + --> $DIR/parse-error.rs:87:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:94:18 + --> $DIR/parse-error.rs:89:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:96:19 + --> $DIR/parse-error.rs:91:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:98:24 + --> $DIR/parse-error.rs:93:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:100:30 + --> $DIR/parse-error.rs:95:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:102:25 + --> $DIR/parse-error.rs:97:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:104:25 + --> $DIR/parse-error.rs:99:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:106:25 + --> $DIR/parse-error.rs:101:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: arguments are not allowed after options - --> $DIR/parse-error.rs:108:30 - | -LL | global_asm!("{}", options(), const FOO); - | --------- ^^^^^^^^^ argument - | | - | previous options - error: expected string literal - --> $DIR/parse-error.rs:110:29 + --> $DIR/parse-error.rs:104:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:112:33 + --> $DIR/parse-error.rs:106:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:114:34 + --> $DIR/parse-error.rs:108:34 | LL | global_asm!("", clobber_abi("C", FOO)); | ^^^ not a string literal -error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:116:37 - | -LL | global_asm!("{}", clobber_abi("C"), const FOO); - | ---------------- ^^^^^^^^^ argument - | | - | clobber_abi - error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:116:19 + --> $DIR/parse-error.rs:110:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:119:28 +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:112:28 | LL | global_asm!("", options(), clobber_abi("C")); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options + | ^^^^^^^^^^^^^^^^ -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:121:30 +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:114:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options + | ^^^^^^^^^^^^^^^^ error: duplicate argument named `a` - --> $DIR/parse-error.rs:123:35 + --> $DIR/parse-error.rs:116:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -343,7 +275,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:123:35 + --> $DIR/parse-error.rs:116:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -351,19 +283,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` - --> $DIR/parse-error.rs:126:28 + --> $DIR/parse-error.rs:119:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:128:30 + --> $DIR/parse-error.rs:121:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: asm template must be a string literal - --> $DIR/parse-error.rs:130:13 + --> $DIR/parse-error.rs:123:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -371,7 +303,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:132:20 + --> $DIR/parse-error.rs:125:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -388,7 +320,7 @@ LL | asm!("{}", options(), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:48:44 + --> $DIR/parse-error.rs:47:44 | LL | let mut foo = 0; | ----------- help: consider using `const` instead of `let`: `const foo` @@ -397,7 +329,16 @@ LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:55:31 + --> $DIR/parse-error.rs:50:55 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), clobber_abi("C"), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:52:31 | LL | let mut foo = 0; | ----------- help: consider using `const` instead of `let`: `const foo` @@ -406,7 +347,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:55:46 + --> $DIR/parse-error.rs:52:46 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -415,7 +356,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:62:45 + --> $DIR/parse-error.rs:59:45 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -424,7 +365,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:65:45 + --> $DIR/parse-error.rs:61:45 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -433,7 +374,7 @@ LL | asm!("{a}", in("x0") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:68:41 + --> $DIR/parse-error.rs:63:41 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -441,6 +382,6 @@ LL | let mut bar = 0; LL | asm!("{1}", in("x0") foo, const bar); | ^^^ non-constant value -error: aborting due to 64 previous errors +error: aborting due to 57 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr index bb6a222b22ee7..b16f9a06c2abe 100644 --- a/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr +++ b/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr @@ -81,6 +81,11 @@ note: explicit register arguments cannot be used in the asm template | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ +help: use the register name directly in the assembly code + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ error: asm template modifier must be a single character --> $DIR/bad-template.rs:50:17 diff --git a/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr index bb6a222b22ee7..b16f9a06c2abe 100644 --- a/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr +++ b/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr @@ -81,6 +81,11 @@ note: explicit register arguments cannot be used in the asm template | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ +help: use the register name directly in the assembly code + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ error: asm template modifier must be a single character --> $DIR/bad-template.rs:50:17 diff --git a/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr index 903b5e959f3ef..41ac37c33c2e0 100644 --- a/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr +++ b/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr @@ -81,6 +81,11 @@ note: explicit register arguments cannot be used in the asm template | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ +help: use the register name directly in the assembly code + --> $DIR/bad-template.rs:45:20 + | +LL | asm!("{}", in("eax") foo); + | ^^^^^^^^^^^^^ error: asm template modifier must be a single character --> $DIR/bad-template.rs:50:17 diff --git a/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr index 903b5e959f3ef..41ac37c33c2e0 100644 --- a/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr +++ b/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr @@ -81,6 +81,11 @@ note: explicit register arguments cannot be used in the asm template | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ +help: use the register name directly in the assembly code + --> $DIR/bad-template.rs:45:20 + | +LL | asm!("{}", in("eax") foo); + | ^^^^^^^^^^^^^ error: asm template modifier must be a single character --> $DIR/bad-template.rs:50:17 diff --git a/tests/ui/asm/x86_64/parse-error.rs b/tests/ui/asm/x86_64/parse-error.rs index 9aeb6b2853fba..2e714d464ae74 100644 --- a/tests/ui/asm/x86_64/parse-error.rs +++ b/tests/ui/asm/x86_64/parse-error.rs @@ -37,8 +37,7 @@ fn main() { asm!("", options(nomem, foo)); //~^ ERROR expected one of asm!("{}", options(), const foo); - //~^ ERROR arguments are not allowed after options - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("", clobber_abi()); //~^ ERROR at least one abi must be provided asm!("", clobber_abi(foo)); @@ -48,12 +47,10 @@ fn main() { asm!("", clobber_abi("C", foo)); //~^ ERROR expected string literal asm!("{}", clobber_abi("C"), const foo); - //~^ ERROR arguments are not allowed after clobber_abi - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("", options(), clobber_abi("C")); - //~^ ERROR clobber_abi is not allowed after options asm!("{}", options(), clobber_abi("C"), const foo); - //~^ ERROR clobber_abi is not allowed after options + //~^ ERROR attempt to use a non-constant value in a constant asm!("{a}", a = const foo, a = const bar); //~^ ERROR duplicate argument named `a` //~^^ ERROR argument never used @@ -62,11 +59,9 @@ fn main() { asm!("", a = in("eax") foo); //~^ ERROR explicit register arguments cannot have names asm!("{a}", in("eax") foo, a = const bar); - //~^ ERROR named arguments cannot follow explicit register arguments - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("{a}", in("eax") foo, a = const bar); - //~^ ERROR named arguments cannot follow explicit register arguments - //~^^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant asm!("{1}", in("eax") foo, const bar); //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments //~^^ ERROR attempt to use a non-constant value in a constant @@ -108,7 +103,6 @@ global_asm!("", options(nomem FOO)); global_asm!("", options(nomem, FOO)); //~^ ERROR expected one of global_asm!("{}", options(), const FOO); -//~^ ERROR arguments are not allowed after options global_asm!("", clobber_abi(FOO)); //~^ ERROR expected string literal global_asm!("", clobber_abi("C" FOO)); @@ -116,12 +110,11 @@ global_asm!("", clobber_abi("C" FOO)); global_asm!("", clobber_abi("C", FOO)); //~^ ERROR expected string literal global_asm!("{}", clobber_abi("C"), const FOO); -//~^ ERROR arguments are not allowed after clobber_abi -//~^^ ERROR `clobber_abi` cannot be used with `global_asm!` +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("", options(), clobber_abi("C")); -//~^ ERROR clobber_abi is not allowed after options +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("{}", options(), clobber_abi("C"), const FOO); -//~^ ERROR clobber_abi is not allowed after options +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("", clobber_abi("C"), clobber_abi("C")); //~^ ERROR `clobber_abi` cannot be used with `global_asm!` global_asm!("{a}", a = const FOO, a = const BAR); diff --git a/tests/ui/asm/x86_64/parse-error.stderr b/tests/ui/asm/x86_64/parse-error.stderr index 57702c37b7ce2..0c9d6f71529c1 100644 --- a/tests/ui/asm/x86_64/parse-error.stderr +++ b/tests/ui/asm/x86_64/parse-error.stderr @@ -82,64 +82,32 @@ error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `no LL | asm!("", options(nomem, foo)); | ^^^ expected one of 10 possible tokens -error: arguments are not allowed after options - --> $DIR/parse-error.rs:39:31 - | -LL | asm!("{}", options(), const foo); - | --------- ^^^^^^^^^ argument - | | - | previous options - error: at least one abi must be provided as an argument to `clobber_abi` - --> $DIR/parse-error.rs:42:30 + --> $DIR/parse-error.rs:41:30 | LL | asm!("", clobber_abi()); | ^ error: expected string literal - --> $DIR/parse-error.rs:44:30 + --> $DIR/parse-error.rs:43:30 | LL | asm!("", clobber_abi(foo)); | ^^^ not a string literal error: expected one of `)` or `,`, found `foo` - --> $DIR/parse-error.rs:46:34 + --> $DIR/parse-error.rs:45:34 | LL | asm!("", clobber_abi("C" foo)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:48:35 + --> $DIR/parse-error.rs:47:35 | LL | asm!("", clobber_abi("C", foo)); | ^^^ not a string literal -error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:50:38 - | -LL | asm!("{}", clobber_abi("C"), const foo); - | ---------------- ^^^^^^^^^ argument - | | - | clobber_abi - -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:53:29 - | -LL | asm!("", options(), clobber_abi("C")); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options - -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:55:31 - | -LL | asm!("{}", options(), clobber_abi("C"), const foo); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options - error: duplicate argument named `a` - --> $DIR/parse-error.rs:57:36 + --> $DIR/parse-error.rs:54:36 | LL | asm!("{a}", a = const foo, a = const bar); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -147,7 +115,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | previously here error: argument never used - --> $DIR/parse-error.rs:57:36 + --> $DIR/parse-error.rs:54:36 | LL | asm!("{a}", a = const foo, a = const bar); | ^^^^^^^^^^^^^ argument never used @@ -155,29 +123,13 @@ LL | asm!("{a}", a = const foo, a = const bar); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: explicit register arguments cannot have names - --> $DIR/parse-error.rs:62:18 + --> $DIR/parse-error.rs:59:18 | LL | asm!("", a = in("eax") foo); | ^^^^^^^^^^^^^^^^^ -error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:64:36 - | -LL | asm!("{a}", in("eax") foo, a = const bar); - | ------------- ^^^^^^^^^^^^^ named argument - | | - | explicit register argument - -error: named arguments cannot follow explicit register arguments - --> $DIR/parse-error.rs:67:36 - | -LL | asm!("{a}", in("eax") foo, a = const bar); - | ------------- ^^^^^^^^^^^^^ named argument - | | - | explicit register argument - error: positional arguments cannot follow named arguments or explicit register arguments - --> $DIR/parse-error.rs:70:36 + --> $DIR/parse-error.rs:65:36 | LL | asm!("{1}", in("eax") foo, const bar); | ------------- ^^^^^^^^^ positional argument @@ -185,19 +137,19 @@ LL | asm!("{1}", in("eax") foo, const bar); | explicit register argument error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` - --> $DIR/parse-error.rs:73:29 + --> $DIR/parse-error.rs:68:29 | LL | asm!("", options(), ""); | ^^ expected one of 9 possible tokens error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:75:33 + --> $DIR/parse-error.rs:70:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); | ^^^^ expected one of 9 possible tokens error: asm template must be a string literal - --> $DIR/parse-error.rs:77:14 + --> $DIR/parse-error.rs:72:14 | LL | asm!(format!("{{{}}}", 0), in(reg) foo); | ^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +157,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:79:21 + --> $DIR/parse-error.rs:74:21 | LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); | ^^^^^^^^^^^^^^^^^^^^ @@ -213,141 +165,121 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: _ cannot be used for input operands - --> $DIR/parse-error.rs:81:28 + --> $DIR/parse-error.rs:76:28 | LL | asm!("{}", in(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:83:31 + --> $DIR/parse-error.rs:78:31 | LL | asm!("{}", inout(reg) _); | ^ error: _ cannot be used for input operands - --> $DIR/parse-error.rs:85:35 + --> $DIR/parse-error.rs:80:35 | LL | asm!("{}", inlateout(reg) _); | ^ error: requires at least a template string argument - --> $DIR/parse-error.rs:92:1 + --> $DIR/parse-error.rs:87:1 | LL | global_asm!(); | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:94:13 + --> $DIR/parse-error.rs:89:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:96:18 + --> $DIR/parse-error.rs:91:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:98:19 + --> $DIR/parse-error.rs:93:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:100:24 + --> $DIR/parse-error.rs:95:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:102:30 + --> $DIR/parse-error.rs:97:30 | LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` - --> $DIR/parse-error.rs:104:25 + --> $DIR/parse-error.rs:99:25 | LL | global_asm!("", options(FOO)); | ^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:106:25 + --> $DIR/parse-error.rs:101:25 | LL | global_asm!("", options(nomem FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/parse-error.rs:108:25 + --> $DIR/parse-error.rs:103:25 | LL | global_asm!("", options(nomem, FOO)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: arguments are not allowed after options - --> $DIR/parse-error.rs:110:30 - | -LL | global_asm!("{}", options(), const FOO); - | --------- ^^^^^^^^^ argument - | | - | previous options - error: expected string literal - --> $DIR/parse-error.rs:112:29 + --> $DIR/parse-error.rs:106:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected one of `)` or `,`, found `FOO` - --> $DIR/parse-error.rs:114:33 + --> $DIR/parse-error.rs:108:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected one of `)` or `,` error: expected string literal - --> $DIR/parse-error.rs:116:34 + --> $DIR/parse-error.rs:110:34 | LL | global_asm!("", clobber_abi("C", FOO)); | ^^^ not a string literal -error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:118:37 - | -LL | global_asm!("{}", clobber_abi("C"), const FOO); - | ---------------- ^^^^^^^^^ argument - | | - | clobber_abi - error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:118:19 + --> $DIR/parse-error.rs:112:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:121:28 +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:114:28 | LL | global_asm!("", options(), clobber_abi("C")); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options + | ^^^^^^^^^^^^^^^^ -error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:123:30 +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:116:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); - | --------- ^^^^^^^^^^^^^^^^ - | | - | options + | ^^^^^^^^^^^^^^^^ error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:125:17 + --> $DIR/parse-error.rs:118:17 | LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ error: duplicate argument named `a` - --> $DIR/parse-error.rs:127:35 + --> $DIR/parse-error.rs:120:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -355,7 +287,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:127:35 + --> $DIR/parse-error.rs:120:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -363,19 +295,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` - --> $DIR/parse-error.rs:130:28 + --> $DIR/parse-error.rs:123:28 | LL | global_asm!("", options(), ""); | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` - --> $DIR/parse-error.rs:132:30 + --> $DIR/parse-error.rs:125:30 | LL | global_asm!("{}", const FOO, "{}", const FOO); | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` error: asm template must be a string literal - --> $DIR/parse-error.rs:134:13 + --> $DIR/parse-error.rs:127:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -383,7 +315,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm template must be a string literal - --> $DIR/parse-error.rs:136:20 + --> $DIR/parse-error.rs:129:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -400,7 +332,7 @@ LL | asm!("{}", options(), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:50:44 + --> $DIR/parse-error.rs:49:44 | LL | let mut foo = 0; | ----------- help: consider using `const` instead of `let`: `const foo` @@ -409,7 +341,16 @@ LL | asm!("{}", clobber_abi("C"), const foo); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:57:31 + --> $DIR/parse-error.rs:52:55 + | +LL | let mut foo = 0; + | ----------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), clobber_abi("C"), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:54:31 | LL | let mut foo = 0; | ----------- help: consider using `const` instead of `let`: `const foo` @@ -418,7 +359,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:57:46 + --> $DIR/parse-error.rs:54:46 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -427,7 +368,7 @@ LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:64:46 + --> $DIR/parse-error.rs:61:46 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -436,7 +377,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:67:46 + --> $DIR/parse-error.rs:63:46 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -445,7 +386,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | ^^^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/parse-error.rs:70:42 + --> $DIR/parse-error.rs:65:42 | LL | let mut bar = 0; | ----------- help: consider using `const` instead of `let`: `const bar` @@ -453,6 +394,6 @@ LL | let mut bar = 0; LL | asm!("{1}", in("eax") foo, const bar); | ^^^ non-constant value -error: aborting due to 66 previous errors +error: aborting due to 59 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr index d40ffc48a29f9..21dbc606321ff 100644 --- a/tests/ui/coherence/coherence-impls-copy.stderr +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -52,19 +52,19 @@ LL | impl Copy for [MyType] {} | = note: define and implement a trait or new type instead -error[E0206]: the trait `Copy` may not be implemented for this type +error[E0206]: the trait `Copy` cannot be implemented for this type --> $DIR/coherence-impls-copy.rs:21:15 | LL | impl Copy for &'static mut MyType {} | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration -error[E0206]: the trait `Copy` may not be implemented for this type +error[E0206]: the trait `Copy` cannot be implemented for this type --> $DIR/coherence-impls-copy.rs:25:15 | LL | impl Copy for (MyType, MyType) {} | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration -error[E0206]: the trait `Copy` may not be implemented for this type +error[E0206]: the trait `Copy` cannot be implemented for this type --> $DIR/coherence-impls-copy.rs:30:15 | LL | impl Copy for [MyType] {} diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index 80bbe387ac719..97fd3f719bfbf 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -31,7 +31,7 @@ impl<'tcx, T> Clone for List<'tcx, T> { } impl<'tcx, T> Copy for List<'tcx, T> {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn assert_is_copy() {} diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index 168ee57263d2a..7b6dd4b380f6f 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/deep-bad-copy-reason.rs:33:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); diff --git a/tests/ui/coherence/illegal-copy-bad-projection.rs b/tests/ui/coherence/illegal-copy-bad-projection.rs new file mode 100644 index 0000000000000..797443a0abe5a --- /dev/null +++ b/tests/ui/coherence/illegal-copy-bad-projection.rs @@ -0,0 +1,16 @@ +trait AsPtr { + type Ptr; +} + +impl AsPtr for () { + type Ptr = *const void; + //~^ ERROR cannot find type `void` in this scope +} + +#[derive(Copy, Clone)] +struct Foo { + p: <() as AsPtr>::Ptr, + // Do not report a "`Copy` cannot be implemented" here. +} + +fn main() {} diff --git a/tests/ui/coherence/illegal-copy-bad-projection.stderr b/tests/ui/coherence/illegal-copy-bad-projection.stderr new file mode 100644 index 0000000000000..8fed9ba23b24b --- /dev/null +++ b/tests/ui/coherence/illegal-copy-bad-projection.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `void` in this scope + --> $DIR/illegal-copy-bad-projection.rs:6:23 + | +LL | type Ptr = *const void; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/bad-generic-in-copy-impl.rs b/tests/ui/const-generics/bad-generic-in-copy-impl.rs new file mode 100644 index 0000000000000..b5663464cf422 --- /dev/null +++ b/tests/ui/const-generics/bad-generic-in-copy-impl.rs @@ -0,0 +1,9 @@ +#[derive(Copy, Clone)] +pub struct Foo { + x: [u8; SIZE], + //~^ ERROR mismatched types +} + +const SIZE: u32 = 1; + +fn main() {} diff --git a/tests/ui/const-generics/bad-generic-in-copy-impl.stderr b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr new file mode 100644 index 0000000000000..25701ce68ccc8 --- /dev/null +++ b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/bad-generic-in-copy-impl.rs:3:13 + | +LL | x: [u8; SIZE], + | ^^^^ expected `usize`, found `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index bb3017b6ec26a..52f1f30a4087d 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -1,4 +1,4 @@ -error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor +error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/E0184.rs:1:10 | LL | #[derive(Copy)] diff --git a/tests/ui/error-codes/E0206.rs b/tests/ui/error-codes/E0206.rs index 0f3d427ce11ac..74738d81015eb 100644 --- a/tests/ui/error-codes/E0206.rs +++ b/tests/ui/error-codes/E0206.rs @@ -2,7 +2,7 @@ struct Bar; impl Copy for &'static mut Bar { } -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() { } diff --git a/tests/ui/error-codes/E0206.stderr b/tests/ui/error-codes/E0206.stderr index 57ae2647d339c..60d8d7bfe983d 100644 --- a/tests/ui/error-codes/E0206.stderr +++ b/tests/ui/error-codes/E0206.stderr @@ -1,4 +1,4 @@ -error[E0206]: the trait `Copy` may not be implemented for this type +error[E0206]: the trait `Copy` cannot be implemented for this type --> $DIR/E0206.rs:4:15 | LL | impl Copy for &'static mut Bar { } diff --git a/tests/ui/exclusive-drop-and-copy.rs b/tests/ui/exclusive-drop-and-copy.rs index 7a251671ee996..210ecaed7567d 100644 --- a/tests/ui/exclusive-drop-and-copy.rs +++ b/tests/ui/exclusive-drop-and-copy.rs @@ -1,13 +1,13 @@ // issue #20126 -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented struct Foo; impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented struct Bar(::std::marker::PhantomData); impl Drop for Bar { diff --git a/tests/ui/exclusive-drop-and-copy.stderr b/tests/ui/exclusive-drop-and-copy.stderr index 8649c8abbfa7f..546079422a733 100644 --- a/tests/ui/exclusive-drop-and-copy.stderr +++ b/tests/ui/exclusive-drop-and-copy.stderr @@ -1,4 +1,4 @@ -error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor +error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/exclusive-drop-and-copy.rs:3:10 | LL | #[derive(Copy, Clone)] @@ -6,7 +6,7 @@ LL | #[derive(Copy, Clone)] | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor +error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/exclusive-drop-and-copy.rs:10:10 | LL | #[derive(Copy, Clone)] diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs index 61c77cc1ff39b..aff37d95a3f3e 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/issues/issue-27340.rs @@ -1,6 +1,6 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(Foo); fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 40889b8666839..9caaffd9c9a21 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-27340.rs:2:10 | LL | #[derive(Copy, Clone)] diff --git a/tests/ui/opt-in-copy.rs b/tests/ui/opt-in-copy.rs index 0b48418e464a6..d0257b5745d8b 100644 --- a/tests/ui/opt-in-copy.rs +++ b/tests/ui/opt-in-copy.rs @@ -5,7 +5,7 @@ struct IWantToCopyThis { } impl Copy for IWantToCopyThis {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type enum CantCopyThisEither { A, @@ -17,6 +17,6 @@ enum IWantToCopyThisToo { } impl Copy for IWantToCopyThisToo {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/opt-in-copy.stderr b/tests/ui/opt-in-copy.stderr index 4461567df0a2a..258ff16e6e485 100644 --- a/tests/ui/opt-in-copy.stderr +++ b/tests/ui/opt-in-copy.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/opt-in-copy.rs:7:15 | LL | but_i_cant: CantCopyThis, @@ -7,7 +7,7 @@ LL | but_i_cant: CantCopyThis, LL | impl Copy for IWantToCopyThis {} | ^^^^^^^^^^^^^^^ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/opt-in-copy.rs:19:15 | LL | ButICant(CantCopyThisEither), diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 61facba535bff..0829fc2ce9b8c 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/range_traits-2.rs:3:10 | LL | #[derive(Copy, Clone)] diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index e54d17b329ec5..db19d1baec994 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/range_traits-3.rs:3:10 | LL | #[derive(Copy, Clone)] diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index addc525f1fa36..dfc74f87ca715 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/range_traits-6.rs:3:10 | LL | #[derive(Copy, Clone)] diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs index 174de8cdd63fa..8793a05c8a85a 100644 --- a/tests/ui/span/E0204.rs +++ b/tests/ui/span/E0204.rs @@ -2,9 +2,9 @@ struct Foo { foo: Vec, } -impl Copy for Foo { } //~ ERROR may not be implemented for this type +impl Copy for Foo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR may not be implemented for this type +#[derive(Copy)] //~ ERROR cannot be implemented for this type struct Foo2<'a> { ty: &'a mut bool, } @@ -14,9 +14,9 @@ enum EFoo { Baz, } -impl Copy for EFoo { } //~ ERROR may not be implemented for this type +impl Copy for EFoo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR may not be implemented for this type +#[derive(Copy)] //~ ERROR cannot be implemented for this type enum EFoo2<'a> { Bar(&'a mut bool), Baz, diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index 0b2166eed7ead..3a0afb541ba8d 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/E0204.rs:5:15 | LL | foo: Vec, @@ -7,7 +7,7 @@ LL | foo: Vec, LL | impl Copy for Foo { } | ^^^ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/E0204.rs:7:10 | LL | #[derive(Copy)] @@ -18,7 +18,7 @@ LL | ty: &'a mut bool, | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/E0204.rs:17:15 | LL | Bar { x: Vec }, @@ -27,7 +27,7 @@ LL | Bar { x: Vec }, LL | impl Copy for EFoo { } | ^^^^ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/E0204.rs:19:10 | LL | #[derive(Copy)] diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 304360d48a261..47b35b412c037 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -7,7 +7,7 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ pub loc: Vector2, pub size: Vector2 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 14e1fbb33112a..771e9105c6211 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -7,7 +7,7 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ pub loc: Vector2, pub size: Vector2 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index faf730a5ce321..09696e0613e7c 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 | LL | #[derive(Debug, Copy, Clone)] @@ -6,16 +6,12 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct AABB{ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` -LL | pub size: Vector2 - | -------------------- this field does not implement `Copy` | note: the `Copy` impl for `Vector2` requires that `K: Debug` --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 | LL | pub loc: Vector2, | ^^^^^^^^^^ -LL | pub size: Vector2 - | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting this bound | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 52163bddd4ff5..9c7b7ba099c43 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -6,7 +6,7 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ pub loc: Vector2, pub size: Vector2 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 11bc540991775..8585fe47bf345 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 | LL | #[derive(Debug, Copy, Clone)] @@ -6,16 +6,12 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct AABB{ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` -LL | pub size: Vector2 - | -------------------- this field does not implement `Copy` | note: the `Copy` impl for `Vector2` requires that `K: Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 | LL | pub loc: Vector2, | ^^^^^^^^^^ -LL | pub size: Vector2 - | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` | diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed index 691e7553a0952..f32c61a99bb8c 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -14,6 +14,6 @@ impl Clone for OnlyCopyIfDisplay { impl Copy for OnlyCopyIfDisplay {} impl Copy for Wrapper> {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs index e3185e7eff855..d7725f4a3743d 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -14,6 +14,6 @@ impl Clone for OnlyCopyIfDisplay { impl Copy for OnlyCopyIfDisplay {} impl Copy for Wrapper> {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 9e6f0d9ebbd27..856d8db381bd8 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 | LL | struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed index 32a7215c5bdc3..1139b315313fc 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -4,6 +4,6 @@ struct Wrapper(T); impl Copy for Wrapper {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs index c688f4d41ee9b..19549248efc23 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -4,6 +4,6 @@ struct Wrapper(T); impl Copy for Wrapper {} -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index fe2d133c8aa74..ec3e4f23a649e 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 | LL | struct Wrapper(T); diff --git a/tests/ui/test-attrs/tests-listing-format-default.rs b/tests/ui/test-attrs/tests-listing-format-default.rs new file mode 100644 index 0000000000000..d5df4b57b0591 --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-default.rs @@ -0,0 +1,18 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --list +// run-pass +// check-run-results + +// Checks the listing of tests with no --format arguments. + +#![cfg(test)] +#[test] +fn m_test() {} + +#[test] +#[ignore = "not yet implemented"] +fn z_test() {} + +#[test] +fn a_test() {} diff --git a/tests/ui/test-attrs/tests-listing-format-default.run.stdout b/tests/ui/test-attrs/tests-listing-format-default.run.stdout new file mode 100644 index 0000000000000..72337daf02cdf --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-default.run.stdout @@ -0,0 +1,5 @@ +a_test: test +m_test: test +z_test: test + +3 tests, 0 benchmarks diff --git a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.rs b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.rs new file mode 100644 index 0000000000000..5247f1f8f1746 --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.rs @@ -0,0 +1,18 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --list --format json +// run-fail +// check-run-results + +// Checks that --format json does not work without -Zunstable-options. + +#![cfg(test)] +#[test] +fn m_test() {} + +#[test] +#[ignore = "not yet implemented"] +fn z_test() {} + +#[test] +fn a_test() {} diff --git a/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr new file mode 100644 index 0000000000000..9f6276300a0bd --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-json-without-unstableopts.run.stderr @@ -0,0 +1 @@ +error: The "json" format is only accepted on the nightly compiler diff --git a/tests/ui/test-attrs/tests-listing-format-json.rs b/tests/ui/test-attrs/tests-listing-format-json.rs new file mode 100644 index 0000000000000..24c87d551584f --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-json.rs @@ -0,0 +1,18 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --list --format json -Zunstable-options +// run-pass +// check-run-results + +// Checks the listing of tests with --format json. + +#![cfg(test)] +#[test] +fn m_test() {} + +#[test] +#[ignore = "not yet implemented"] +fn z_test() {} + +#[test] +fn a_test() {} diff --git a/tests/ui/test-attrs/tests-listing-format-json.run.stdout b/tests/ui/test-attrs/tests-listing-format-json.run.stdout new file mode 100644 index 0000000000000..b97a031bae4bd --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-json.run.stdout @@ -0,0 +1,5 @@ +{ "type": "suite", "event": "discovery" } +{ "type": "test", "event": "discovered", "name": "a_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 18, "start_col": 4, "end_line": 18, "end_col": 10 } +{ "type": "test", "event": "discovered", "name": "m_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 11, "start_col": 4, "end_line": 11, "end_col": 10 } +{ "type": "test", "event": "discovered", "name": "z_test", "ignore": true, "ignore_message": "not yet implemented", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 15, "start_col": 4, "end_line": 15, "end_col": 10 } +{ "type": "suite", "event": "completed", "tests": 3, "benchmarks": 0, "total": 3, "ignored": 1 } diff --git a/tests/ui/test-attrs/tests-listing-format-terse.rs b/tests/ui/test-attrs/tests-listing-format-terse.rs new file mode 100644 index 0000000000000..7835f71759cb4 --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-terse.rs @@ -0,0 +1,18 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --list --format terse +// run-pass +// check-run-results + +// Checks the listing of tests with --format terse. + +#![cfg(test)] +#[test] +fn m_test() {} + +#[test] +#[ignore = "not yet implemented"] +fn z_test() {} + +#[test] +fn a_test() {} diff --git a/tests/ui/test-attrs/tests-listing-format-terse.run.stdout b/tests/ui/test-attrs/tests-listing-format-terse.run.stdout new file mode 100644 index 0000000000000..22afe104bfb1d --- /dev/null +++ b/tests/ui/test-attrs/tests-listing-format-terse.run.stdout @@ -0,0 +1,3 @@ +a_test: test +m_test: test +z_test: test diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr index edd94d2010b96..1304252118413 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/copy-is-not-modulo-regions.rs:13:21 | LL | struct Bar<'lt>(Foo<'lt>); diff --git a/tests/ui/traits/copy-is-not-modulo-regions.rs b/tests/ui/traits/copy-is-not-modulo-regions.rs index adb8702376977..b899083747afa 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.rs +++ b/tests/ui/traits/copy-is-not-modulo-regions.rs @@ -11,7 +11,7 @@ struct Bar<'lt>(Foo<'lt>); #[cfg(not_static)] impl<'any> Copy for Bar<'any> {} -//[not_static]~^ the trait `Copy` may not be implemented for this type +//[not_static]~^ the trait `Copy` cannot be implemented for this type #[cfg(yes_static)] impl<'any> Copy for Bar<'static> {} diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index 005939e0c46e4..683a85a32c1c6 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -1,5 +1,5 @@ #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type struct Foo(N, NotDefined, ::Item, Vec, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope @@ -7,7 +7,7 @@ struct Foo(N, NotDefined, ::Item, Vec, String); //~| ERROR cannot find type `N` in this scope #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` may not be implemented for this type +//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(T, N, NotDefined, ::Item, Vec, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 5063fdca09273..4f72db60a1647 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -60,7 +60,7 @@ error[E0412]: cannot find type `NotDefined` in this scope LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-50480.rs:1:17 | LL | #[derive(Clone, Copy)] @@ -73,7 +73,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-50480.rs:9:17 | LL | #[derive(Clone, Copy)] diff --git a/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs new file mode 100644 index 0000000000000..d1c6b1077e8ef --- /dev/null +++ b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs @@ -0,0 +1,39 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +trait Mirror { + type Item; +} + +struct Wrapper(T); +impl Mirror for Wrapper { + type Item = T; +} + +fn mirror() +where + Wrapper: Mirror, +{ +} + +fn main() { + mirror::<_ /* ?0 */>(); + + // Solving ` as Mirror>::Item = i32` + + // First, we replace the term with a fresh infer var: + // ` as Mirror>::Item = ?1` + + // We select the impl candidate on line #6, which leads us to learn that + // `?0 == ?1`. + + // That should be reflected in our canonical response, which should have + // `^0 = ^0, ^1 = ^0` + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // !! We used to return a totally unconstrained response here :< !! + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // Then, during the "equate term" part of the projection solving, we + // instantiate the response from the unconstrained projection predicate, + // and equate `?0 == i32`. +} diff --git a/tests/ui/traits/new-solver/deduce-ty-from-object.rs b/tests/ui/traits/new-solver/deduce-ty-from-object.rs new file mode 100644 index 0000000000000..7398bce7b61cf --- /dev/null +++ b/tests/ui/traits/new-solver/deduce-ty-from-object.rs @@ -0,0 +1,6 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +fn main() { + let x: Box> = Box::new(std::iter::empty()); +} diff --git a/tests/ui/traits/unsend-future.rs b/tests/ui/traits/unsend-future.rs new file mode 100644 index 0000000000000..fbbc07b11e743 --- /dev/null +++ b/tests/ui/traits/unsend-future.rs @@ -0,0 +1,21 @@ +// edition:2021 + +// issue 108897 +trait Handler {} +impl Handler for F +where + Fut: Send, + F: FnOnce() -> Fut, +{} + +fn require_handler(h: H) {} + +async fn handler() { + let a = &1 as *const i32; + async {}.await; +} + +fn main() { + require_handler(handler) + //~^ ERROR future cannot be sent between threads safely +} diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr new file mode 100644 index 0000000000000..4aaa7c4a92426 --- /dev/null +++ b/tests/ui/traits/unsend-future.stderr @@ -0,0 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/unsend-future.rs:19:21 + | +LL | require_handler(handler) + | ^^^^^^^ future returned by `handler` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `*const i32` +note: future is not `Send` as this value is used across an await + --> $DIR/unsend-future.rs:15:13 + | +LL | let a = &1 as *const i32; + | - has type `*const i32` which is not `Send` +LL | async {}.await; + | ^^^^^^ await occurs here, with `a` maybe used later +LL | } + | - `a` is later dropped here +note: required by a bound in `require_handler` + --> $DIR/unsend-future.rs:11:23 + | +LL | fn require_handler(h: H) {} + | ^^^^^^^ required by this bound in `require_handler` + +error: aborting due to previous error + diff --git a/tests/ui/union/field_checks.rs b/tests/ui/union/field_checks.rs index d5d1e44ac855c..bb4eccb4cf896 100644 --- a/tests/ui/union/field_checks.rs +++ b/tests/ui/union/field_checks.rs @@ -21,15 +21,15 @@ union U24 { // OK } union U3 { - a: String, //~ ERROR unions cannot contain fields that may need dropping + a: String, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U32 { // field that does not drop but is not `Copy`, either - a: std::cell::RefCell, //~ ERROR unions cannot contain fields that may need dropping + a: std::cell::RefCell, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U4 { - a: T, //~ ERROR unions cannot contain fields that may need dropping + a: T, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U5 { // Having a drop impl is OK @@ -41,11 +41,11 @@ impl Drop for U5 { } union U5Nested { // a nested union that drops is NOT OK - nest: U5, //~ ERROR unions cannot contain fields that may need dropping + nest: U5, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U5Nested2 { // for now we don't special-case empty arrays - nest: [U5; 0], //~ ERROR unions cannot contain fields that may need dropping + nest: [U5; 0], //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U6 { // OK diff --git a/tests/ui/union/field_checks.stderr b/tests/ui/union/field_checks.stderr index 1f97e97ac6ede..32407a749709c 100644 --- a/tests/ui/union/field_checks.stderr +++ b/tests/ui/union/field_checks.stderr @@ -1,59 +1,59 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:24:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:28:5 | LL | a: std::cell::RefCell, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop>, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:32:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:44:5 | LL | nest: U5, | ^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | nest: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:48:5 | LL | nest: [U5; 0], | ^^^^^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | nest: std::mem::ManuallyDrop<[U5; 0]>, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/issue-41073.rs b/tests/ui/union/issue-41073.rs index 4dfdc606bb409..f7a82b4e7cf5d 100644 --- a/tests/ui/union/issue-41073.rs +++ b/tests/ui/union/issue-41073.rs @@ -1,5 +1,5 @@ union Test { - a: A, //~ ERROR unions cannot contain fields that may need dropping + a: A, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union b: B } diff --git a/tests/ui/union/issue-41073.stderr b/tests/ui/union/issue-41073.stderr index b3887fa0f90be..ae1c4dfed9a23 100644 --- a/tests/ui/union/issue-41073.stderr +++ b/tests/ui/union/issue-41073.stderr @@ -1,11 +1,11 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/issue-41073.rs:2:5 | LL | a: A, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/union-copy.rs b/tests/ui/union/union-copy.rs index 5c3f8d9089819..7ad0a11c6ac6e 100644 --- a/tests/ui/union/union-copy.rs +++ b/tests/ui/union/union-copy.rs @@ -9,6 +9,6 @@ union W { } impl Copy for U {} // OK -impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type +impl Copy for W {} //~ ERROR the trait `Copy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/union/union-copy.stderr b/tests/ui/union/union-copy.stderr index 53ee4dd2e5bdb..ff6fa48db90fd 100644 --- a/tests/ui/union/union-copy.stderr +++ b/tests/ui/union/union-copy.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `Copy` may not be implemented for this type +error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/union-copy.rs:12:15 | LL | a: std::mem::ManuallyDrop diff --git a/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr index 93fe996d2a477..9861a21cb3d8f 100644 --- a/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr +++ b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -1,35 +1,35 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/union-with-drop-fields.rs b/tests/ui/union/union-with-drop-fields.rs index a7a8b69e784ab..9720830fb1ff2 100644 --- a/tests/ui/union/union-with-drop-fields.rs +++ b/tests/ui/union/union-with-drop-fields.rs @@ -8,7 +8,7 @@ union U { } union W { - a: String, //~ ERROR unions cannot contain fields that may need dropping + a: String, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union b: String, // OK, only one field is reported } @@ -16,12 +16,12 @@ struct S(String); // `S` doesn't implement `Drop` trait, but still has non-trivial destructor union Y { - a: S, //~ ERROR unions cannot contain fields that may need dropping + a: S, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } // We don't know if `T` is trivially-destructable or not until trans union J { - a: T, //~ ERROR unions cannot contain fields that may need dropping + a: T, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union H { diff --git a/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr index 93fe996d2a477..9861a21cb3d8f 100644 --- a/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr +++ b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -1,35 +1,35 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/unresolved-field-isnt-copy.rs b/tests/ui/union/unresolved-field-isnt-copy.rs new file mode 100644 index 0000000000000..7a6d79b2faa88 --- /dev/null +++ b/tests/ui/union/unresolved-field-isnt-copy.rs @@ -0,0 +1,8 @@ +// Unresolved fields are not copy, but also shouldn't report an extra E0740. + +pub union Foo { + x: *const Missing, + //~^ ERROR cannot find type `Missing` in this scope +} + +fn main() {} diff --git a/tests/ui/union/unresolved-field-isnt-copy.stderr b/tests/ui/union/unresolved-field-isnt-copy.stderr new file mode 100644 index 0000000000000..22301582eefc7 --- /dev/null +++ b/tests/ui/union/unresolved-field-isnt-copy.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unresolved-field-isnt-copy.rs:4:15 + | +LL | x: *const Missing, + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`.