From a052f2cce1df8ac5ac9fcd104c948545f8b5f2f4 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 20 Sep 2022 11:55:07 +0000 Subject: [PATCH 01/12] Add the `#[derive_const]` attribute --- .../src/cfg_accessible.rs | 1 + compiler/rustc_builtin_macros/src/derive.rs | 9 ++--- .../src/deriving/bounds.rs | 2 ++ .../src/deriving/clone.rs | 2 ++ .../src/deriving/cmp/eq.rs | 2 ++ .../src/deriving/cmp/ord.rs | 2 ++ .../src/deriving/cmp/partial_eq.rs | 2 ++ .../src/deriving/cmp/partial_ord.rs | 2 ++ .../src/deriving/debug.rs | 2 ++ .../src/deriving/decodable.rs | 2 ++ .../src/deriving/default.rs | 2 ++ .../src/deriving/encodable.rs | 2 ++ .../src/deriving/generic/mod.rs | 6 ++-- .../rustc_builtin_macros/src/deriving/hash.rs | 2 ++ .../rustc_builtin_macros/src/deriving/mod.rs | 35 ++++++++++++------- compiler/rustc_builtin_macros/src/lib.rs | 3 +- compiler/rustc_expand/src/base.rs | 4 ++- compiler/rustc_expand/src/expand.rs | 13 +++---- compiler/rustc_expand/src/proc_macro.rs | 1 + compiler/rustc_resolve/src/macros.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/macros/mod.rs | 13 +++++++ library/core/src/prelude/v1.rs | 4 +++ library/std/src/prelude/v1.rs | 4 +++ src/test/ui/issues/issue-32655.stderr | 14 ++++++-- .../const_derives/derive-const-gate.rs | 4 +++ .../const_derives/derive-const-gate.stderr | 11 ++++++ .../derive-const-non-const-type.rs | 13 +++++++ .../derive-const-non-const-type.stderr | 14 ++++++++ .../const_derives/derive-const-use.rs | 19 ++++++++++ 30 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index cb5359dd1e27e..86df3c44eb334 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -34,6 +34,7 @@ impl MultiItemModifier for Expander { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; let attr = &ecx.attribute(meta_item.clone()); diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e0fb7affb3498..01f237e6ab5fa 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -10,7 +10,7 @@ use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; -pub(crate) struct Expander; +pub(crate) struct Expander(pub bool); impl MultiItemModifier for Expander { fn expand( @@ -19,6 +19,7 @@ impl MultiItemModifier for Expander { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _: bool, ) -> ExpandResult, Annotatable> { let sess = ecx.sess; if report_bad_target(sess, &item, span) { @@ -58,20 +59,20 @@ impl MultiItemModifier for Expander { report_path_args(sess, &meta); meta.path }) - .map(|path| (path, dummy_annotatable(), None)) + .map(|path| (path, dummy_annotatable(), None, self.0)) .collect(); // Do not configure or clone items unless necessary. match &mut resolutions[..] { [] => {} - [(_, first_item, _), others @ ..] => { + [(_, first_item, ..), others @ ..] => { *first_item = cfg_eval( sess, features, item.clone(), ecx.current_expansion.lint_node_id, ); - for (_, item, _) in others { + for (_, item, _, _) in others { *item = first_item.clone(); } } diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 77e0b6c55a80e..3a5b7ecde8a9e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -12,6 +12,7 @@ pub fn expand_deriving_copy( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let trait_def = TraitDef { span, @@ -21,6 +22,7 @@ pub fn expand_deriving_copy( supports_unions: true, methods: Vec::new(), associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c7f2d95e72f0c..6d9be879cd19f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -14,6 +14,7 @@ pub fn expand_deriving_clone( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { // The simple form is `fn clone(&self) -> Self { *self }`, possibly with // some additional `AssertParamIsClone` assertions. @@ -86,6 +87,7 @@ pub fn expand_deriving_clone( combine_substructure: substructure, }], associated_types: Vec::new(), + is_const, }; trait_def.expand_ext(cx, mitem, item, push, is_simple) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 5b556c5c9b9d1..9c01314112a59 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -15,6 +15,7 @@ pub fn expand_deriving_eq( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let span = cx.with_def_site_ctxt(span); let inline = cx.meta_word(span, sym::inline); @@ -41,6 +42,7 @@ pub fn expand_deriving_eq( })), }], associated_types: Vec::new(), + is_const, }; super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push); diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 7262586955811..d5c81c387834e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_ord( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let inline = cx.meta_word(span, sym::inline); let attrs = thin_vec![cx.attribute(inline)]; @@ -33,6 +34,7 @@ pub fn expand_deriving_ord( combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 42ee65b570a2a..11b838a076c6d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let base = true; @@ -88,6 +89,7 @@ pub fn expand_deriving_partial_eq( supports_unions: false, methods, associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 516892aeda96f..107a01190bb40 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_partial_ord( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); let ret_ty = @@ -42,6 +43,7 @@ pub fn expand_deriving_partial_ord( supports_unions: false, methods: vec![partial_cmp_def], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 4af7fd8165388..cf977c0824d8d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_debug( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { // &mut ::std::fmt::Formatter let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); @@ -36,6 +37,7 @@ pub fn expand_deriving_debug( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 7174dbbe7ea8b..a27a068f31a27 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let krate = sym::rustc_serialize; let typaram = sym::__D; @@ -54,6 +55,7 @@ pub fn expand_deriving_rustc_decodable( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index a94c8a996e642..35b23f2f8f31a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_default( mitem: &ast::MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); @@ -46,6 +47,7 @@ pub fn expand_deriving_default( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) } diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index b220e54238f46..f06cf0c56bc70 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let krate = sym::rustc_serialize; let typaram = sym::__S; @@ -138,6 +139,7 @@ pub fn expand_deriving_rustc_encodable( })), }], associated_types: Vec::new(), + is_const, }; trait_def.expand(cx, mitem, item, push) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 3cc160adb5397..78dbe8e5979e2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData}; use rustc_attr as attr; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::RefCell; use std::iter; use std::vec; @@ -200,6 +200,8 @@ pub struct TraitDef<'a> { pub methods: Vec>, pub associated_types: Vec<(Ident, Ty)>, + + pub is_const: bool, } pub struct MethodDef<'a> { @@ -726,7 +728,7 @@ impl<'a> TraitDef<'a> { unsafety: ast::Unsafe::No, polarity: ast::ImplPolarity::Positive, defaultness: ast::Defaultness::Final, - constness: ast::Const::No, + constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, generics: trait_generics, of_trait: opt_trait_ref, self_ty: self_type, diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1f02e7ce7787..ef3da94f9e3f5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -13,6 +13,7 @@ pub fn expand_deriving_hash( mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable), + is_const: bool, ) { let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std); @@ -38,6 +39,7 @@ pub fn expand_deriving_hash( })), }], associated_types: Vec::new(), + is_const, }; hash_trait_def.expand(cx, mitem, item, push); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index a65d0bad6de80..5b89da91d4278 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -38,9 +38,10 @@ pub mod partial_ord; pub mod generic; -pub(crate) struct BuiltinDerive( - pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)), -); +pub(crate) type BuiltinDeriveFn = + fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); + +pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn); impl MultiItemModifier for BuiltinDerive { fn expand( @@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive { span: Span, meta_item: &MetaItem, item: Annotatable, + is_derive_const: bool, ) -> ExpandResult, Annotatable> { // FIXME: Built-in derives often forget to give spans contexts, // so we are doing it here in a centralized way. @@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive { match item { Annotatable::Stmt(stmt) => { if let ast::StmtKind::Item(item) = stmt.into_inner().kind { - (self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| { - // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' - // to the function - items.push(Annotatable::Stmt(P(ast::Stmt { - id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(a.expect_item()), - span, - }))); - }); + (self.0)( + ecx, + span, + meta_item, + &Annotatable::Item(item), + &mut |a| { + // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' + // to the function + items.push(Annotatable::Stmt(P(ast::Stmt { + id: ast::DUMMY_NODE_ID, + kind: ast::StmtKind::Item(a.expect_item()), + span, + }))); + }, + is_derive_const, + ); } else { unreachable!("should have already errored on non-item statement") } } _ => { - (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); + (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const); } } ExpandResult::Ready(items) diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 8aeb3b82a9cd0..ab1fcde16865f 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -97,7 +97,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, - derive: derive::Expander, + derive: derive::Expander(false), + derive_const: derive::Expander(true), global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e1da3ecdec7f4..b3d187848be9c 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -248,6 +248,7 @@ pub trait MultiItemModifier { span: Span, meta_item: &ast::MetaItem, item: Annotatable, + is_derive_const: bool, ) -> ExpandResult, Annotatable>; } @@ -261,6 +262,7 @@ where span: Span, meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult, Annotatable> { ExpandResult::Ready(self(ecx, span, meta_item, item)) } @@ -871,7 +873,7 @@ impl SyntaxExtension { /// Error type that denotes indeterminacy. pub struct Indeterminate; -pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option>)>; +pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option>, bool)>; pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c2add852a0679..a63b59d31cfd9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -319,6 +319,7 @@ pub enum InvocationKind { }, Derive { path: ast::Path, + is_const: bool, item: Annotatable, }, } @@ -460,13 +461,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(path, item, _exts)| { + .map(|(path, item, _exts, is_const)| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = LocalExpnId::fresh_empty(); derive_invocations.push(( Invocation { - kind: InvocationKind::Derive { path, item }, + kind: InvocationKind::Derive { path, item, is_const }, fragment_kind, expansion_data: ExpansionData { id: expn_id, @@ -699,7 +700,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) { Ok(meta) => { - let items = match expander.expand(self.cx, span, &meta, item) { + let items = match expander.expand(self.cx, span, &meta, item, false) { ExpandResult::Ready(items) => items, ExpandResult::Retry(item) => { // Reassemble the original invocation for retrying. @@ -731,19 +732,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::Derive { path, item } => match ext { + InvocationKind::Derive { path, item, is_const } => match ext { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { if let SyntaxExtensionKind::Derive(..) = ext { self.gate_proc_macro_input(&item); } let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path }; - let items = match expander.expand(self.cx, span, &meta, item) { + let items = match expander.expand(self.cx, span, &meta, item, is_const) { ExpandResult::Ready(items) => items, ExpandResult::Retry(item) => { // Reassemble the original invocation for retrying. return ExpandResult::Retry(Invocation { - kind: InvocationKind::Derive { path: meta.path, item }, + kind: InvocationKind::Derive { path: meta.path, item, is_const }, ..invoc }); } diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 1a2ab9d190ebd..e9a6919206894 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -112,6 +112,7 @@ impl MultiItemModifier for DeriveProcMacro { span: Span, _meta_item: &ast::MetaItem, item: Annotatable, + _is_derive_const: bool, ) -> ExpandResult, Annotatable> { // We need special handling for statement items // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dafa10e9e0026..8ef99e5ef968a 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> { has_derive_copy: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() { + for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() { if opt_ext.is_none() { *opt_ext = Some( match self.resolve_macro_path( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 562360130e92f..0a9570979d5af 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -614,6 +614,7 @@ symbols! { deref_mut, deref_target, derive, + derive_const, derive_default_enum, destruct, destructuring_assignment, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index fd96e1ff77d53..e504db8143447 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1464,6 +1464,19 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Attribute macro used to apply derive macros for implementing traits + /// in a const context. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/derive.html + #[unstable(feature = "derive_const", issue = "none")] + #[rustc_builtin_macro] + #[cfg(not(bootstrap))] + pub macro derive_const($item:item) { + /* compiler built-in */ + } + /// Attribute macro applied to a function to turn it into a unit test. /// /// See [the reference] for more info. diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index b566e211cd89d..f52c06d7eadc2 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -78,6 +78,10 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; +#[unstable(feature = "derive_const", issue = "none")] +#[cfg(not(bootstrap))] +pub use crate::macros::builtin::derive_const; + #[unstable( feature = "cfg_accessible", issue = "64797", diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 0226c4d7a2581..93f4a17bbfca3 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -62,6 +62,10 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; +#[unstable(feature = "derive_const", issue = "none")] +#[cfg(not(bootstrap))] +pub use core::prelude::v1::derive_const; + // Do not `doc(no_inline)` either. #[unstable( feature = "cfg_accessible", diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index 2d9ce430a462d..5a758c7002b92 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -2,18 +2,28 @@ error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:3:11 | LL | #[derive_Clone] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` ... LL | foo!(); | ------ in this macro invocation | + ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +LL | pub macro derive_const($item:item) { + | ---------------------- similarly named attribute macro `derive_const` defined here + | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot find attribute `derive_Clone` in this scope --> $DIR/issue-32655.rs:15:7 | LL | #[derive_Clone] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` + | + ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +LL | pub macro derive_const($item:item) { + | ---------------------- similarly named attribute macro `derive_const` defined here error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs new file mode 100644 index 0000000000000..348ca0ab1906b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs @@ -0,0 +1,4 @@ +#[derive_const(Default)] //~ ERROR use of unstable library feature +pub struct S; + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr new file mode 100644 index 0000000000000..cc9bdd2715f70 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'derive_const' + --> $DIR/derive-const-gate.rs:1:3 + | +LL | #[derive_const(Default)] + | ^^^^^^^^^^^^ + | + = help: add `#![feature(derive_const)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs new file mode 100644 index 0000000000000..92843a8a2da48 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs @@ -0,0 +1,13 @@ +#![feature(derive_const)] + +pub struct A; + +impl Default for A { + fn default() -> A { A } +} + +#[derive_const(Default)] +pub struct S(A); +//~^ cannot call non-const fn + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr new file mode 100644 index 0000000000000..d463c774e289e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -0,0 +1,14 @@ +error[E0015]: cannot call non-const fn `::default` in constant functions + --> $DIR/derive-const-non-const-type.rs:10:14 + | +LL | #[derive_const(Default)] + | ------- in this derive macro expansion +LL | pub struct S(A); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs new file mode 100644 index 0000000000000..d1fbeac8598e4 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] + +pub struct A; + +impl const Default for A { + fn default() -> A { A } +} + +impl const PartialEq for A { + fn eq(&self, _: &A) -> bool { true } +} + +#[derive_const(Default, PartialEq)] +pub struct S((), A); + +const _: () = assert!(S((), A) == S::default()); + +fn main() {} From bdced83a2e5fa09d4c5c701d92ddb7e82c844cdd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 9 Nov 2022 18:27:20 +0000 Subject: [PATCH 02/12] Use ObligationCtxt in expected_inputs_for_expected_outputs --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 6ed7a93d46332..c2e1a79984699 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -18,6 +18,7 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ @@ -32,9 +33,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt, -}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use std::collections::hash_map::Entry; use std::slice; @@ -766,34 +765,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expect_args = self .fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. let origin = self.misc(call_span); - let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret); - - // FIXME(#27336) can't use ? here, Try::from_error doesn't default - // to identity so the resulting type is not constrained. - match ures { - Ok(ok) => { - // Process any obligations locally as much as - // we can. We don't care if some things turn - // out unconstrained or ambiguous, as we're - // just trying to get hints here. - let errors = self.save_and_restore_in_snapshot_flag(|_| { - let mut fulfill = >::new(self.tcx); - for obligation in ok.obligations { - fulfill.register_predicate_obligation(self, obligation); - } - fulfill.select_where_possible(self) - }); - - if !errors.is_empty() { - return Err(()); - } - } - Err(_) => return Err(()), + ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); } // Record all the argument types, with the substitutions From 07a47e0708fd8d37dd6f15eec1a4202c7da810e2 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 9 Nov 2022 21:19:31 +0100 Subject: [PATCH 03/12] Emit error in `collecting_trait_impl_trait_tys` on mismatched signatures Previously, a `delay_span_bug` was isssued, failing normalization. This create a `TyKind::Error` in the signature, which caused `compare_predicate_entailment` to swallow its signature mismatch error, causing ICEs because no error was emitted. --- .../src/check/compare_method.rs | 247 ++++++++++-------- .../in-trait/method-signature-matches.rs | 51 ++++ .../in-trait/method-signature-matches.stderr | 84 ++++++ 3 files changed, 277 insertions(+), 105 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/method-signature-matches.rs create mode 100644 src/test/ui/impl-trait/in-trait/method-signature-matches.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 04bf7c83b3208..7c99896b45714 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -9,14 +9,15 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{self, TyCtxtInferExt}; +use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::util::ExplicitSelf; -use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{ - self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, + self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, }; +use rustc_middle::ty::{FnSig, InternalSubsts}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -303,102 +304,19 @@ fn compare_predicate_entailment<'tcx>( } if let Err(terr) = result { - debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); + debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); - let (impl_err_span, trait_err_span) = - extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); - - cause.span = impl_err_span; - - let mut diag = struct_span_err!( - tcx.sess, - cause.span(), - E0053, - "method `{}` has an incompatible type for trait", - trait_m.name - ); - match &terr { - TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) - if trait_m.fn_has_self_parameter => - { - let ty = trait_sig.inputs()[0]; - let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { - ExplicitSelf::ByValue => "self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), - ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {ty}"), - }; - - // When the `impl` receiver is an arbitrary self type, like `self: Box`, the - // span points only at the type `Box, but we want to cover the whole - // argument pattern and type. - let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, body) => tcx - .hir() - .body_param_names(body) - .zip(sig.decl.inputs.iter()) - .map(|(param, ty)| param.span.to(ty.span)) - .next() - .unwrap_or(impl_err_span), - _ => bug!("{:?} is not a method", impl_m), - }; - - diag.span_suggestion( - span, - "change the self-receiver type to match the trait", - sugg, - Applicability::MachineApplicable, - ); - } - TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { - if trait_sig.inputs().len() == *i { - // Suggestion to change output type. We do not suggest in `async` functions - // to avoid complex logic or incorrect output. - match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, _) - if sig.header.asyncness == hir::IsAsync::NotAsync => - { - let msg = "change the output type to match the trait"; - let ap = Applicability::MachineApplicable; - match sig.decl.output { - hir::FnRetTy::DefaultReturn(sp) => { - let sugg = format!("-> {} ", trait_sig.output()); - diag.span_suggestion_verbose(sp, msg, sugg, ap); - } - hir::FnRetTy::Return(hir_ty) => { - let sugg = trait_sig.output(); - diag.span_suggestion(hir_ty.span, msg, sugg, ap); - } - }; - } - _ => {} - }; - } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { - diag.span_suggestion( - impl_err_span, - "change the parameter type to match the trait", - trait_ty, - Applicability::MachineApplicable, - ); - } - } - _ => {} - } - - infcx.err_ctxt().note_type_err( - &mut diag, - &cause, - trait_err_span.map(|sp| (sp, "type in trait".to_owned())), - Some(infer::ValuePairs::Terms(ExpectedFound { - expected: trait_fty.into(), - found: impl_fty.into(), - })), + let emitted = report_trait_method_mismatch( + tcx, + &mut cause, + &infcx, terr, - false, - false, + (trait_m, trait_fty), + (impl_m, impl_fty), + &trait_sig, + &impl_trait_ref, ); - - return Err(diag.emit()); + return Err(emitted); } // Check that all obligations are satisfied by the implementation's @@ -424,6 +342,7 @@ fn compare_predicate_entailment<'tcx>( Ok(()) } +#[instrument(skip(tcx), level = "debug", ret)] pub fn collect_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -437,7 +356,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); - let cause = ObligationCause::new( + let mut cause = ObligationCause::new( return_span, impl_m_hir_id, ObligationCauseCode::CompareImplItemObligation { @@ -514,23 +433,35 @@ pub fn collect_trait_impl_trait_tys<'tcx>( } } + debug!(?trait_sig, ?impl_sig, "equating function signatures"); + + let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); + // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_predicate_entailment`. - match infcx - .at(&cause, param_env) - .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig))) - { + match infcx.at(&cause, param_env).eq(trait_fty, impl_fty) { Ok(infer::InferOk { value: (), obligations }) => { ocx.register_obligations(obligations); } Err(terr) => { - let guar = tcx.sess.delay_span_bug( - return_span, - format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"), + // This function gets called during `compare_predicate_entailment` when normalizing a + // signature that contains RPITIT. When the method signatures don't match, we have to + // emit an error now because `compare_predicate_entailment` will not report the error + // when normalization fails. + let emitted = report_trait_method_mismatch( + tcx, + &mut cause, + infcx, + terr, + (trait_m, trait_fty), + (impl_m, impl_fty), + &trait_sig, + &impl_trait_ref, ); - return Err(guar); + return Err(emitted); } } @@ -690,6 +621,112 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { } } +fn report_trait_method_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + cause: &mut ObligationCause<'tcx>, + infcx: &InferCtxt<'tcx>, + terr: TypeError<'tcx>, + (trait_m, trait_fty): (&AssocItem, Ty<'tcx>), + (impl_m, impl_fty): (&AssocItem, Ty<'tcx>), + trait_sig: &FnSig<'tcx>, + impl_trait_ref: &TraitRef<'tcx>, +) -> ErrorGuaranteed { + let (impl_err_span, trait_err_span) = + extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); + + cause.span = impl_err_span; + + let mut diag = struct_span_err!( + tcx.sess, + cause.span(), + E0053, + "method `{}` has an incompatible type for trait", + trait_m.name + ); + match &terr { + TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) + if trait_m.fn_has_self_parameter => + { + let ty = trait_sig.inputs()[0]; + let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) { + ExplicitSelf::ByValue => "self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), + ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), + _ => format!("self: {ty}"), + }; + + // When the `impl` receiver is an arbitrary self type, like `self: Box`, the + // span points only at the type `Box, but we want to cover the whole + // argument pattern and type. + let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { + ImplItemKind::Fn(ref sig, body) => tcx + .hir() + .body_param_names(body) + .zip(sig.decl.inputs.iter()) + .map(|(param, ty)| param.span.to(ty.span)) + .next() + .unwrap_or(impl_err_span), + _ => bug!("{:?} is not a method", impl_m), + }; + + diag.span_suggestion( + span, + "change the self-receiver type to match the trait", + sugg, + Applicability::MachineApplicable, + ); + } + TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => { + if trait_sig.inputs().len() == *i { + // Suggestion to change output type. We do not suggest in `async` functions + // to avoid complex logic or incorrect output. + match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { + ImplItemKind::Fn(ref sig, _) + if sig.header.asyncness == hir::IsAsync::NotAsync => + { + let msg = "change the output type to match the trait"; + let ap = Applicability::MachineApplicable; + match sig.decl.output { + hir::FnRetTy::DefaultReturn(sp) => { + let sugg = format!("-> {} ", trait_sig.output()); + diag.span_suggestion_verbose(sp, msg, sugg, ap); + } + hir::FnRetTy::Return(hir_ty) => { + let sugg = trait_sig.output(); + diag.span_suggestion(hir_ty.span, msg, sugg, ap); + } + }; + } + _ => {} + }; + } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { + diag.span_suggestion( + impl_err_span, + "change the parameter type to match the trait", + trait_ty, + Applicability::MachineApplicable, + ); + } + } + _ => {} + } + + infcx.err_ctxt().note_type_err( + &mut diag, + &cause, + trait_err_span.map(|sp| (sp, "type in trait".to_owned())), + Some(infer::ValuePairs::Terms(ExpectedFound { + expected: trait_fty.into(), + found: impl_fty.into(), + })), + terr, + false, + false, + ); + + return diag.emit(); +} + fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.rs b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs new file mode 100644 index 0000000000000..c848ee3f643de --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs @@ -0,0 +1,51 @@ +// edition: 2021 + +#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] +#![allow(incomplete_features)] + +trait Uwu { + fn owo(x: ()) -> impl Sized; +} + +impl Uwu for () { + fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait AsyncUwu { + async fn owo(x: ()) {} +} + +impl AsyncUwu for () { + async fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait TooMuch { + fn calm_down_please() -> impl Sized; +} + +impl TooMuch for () { + fn calm_down_please(_: (), _: (), _: ()) {} + //~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 +} + +trait TooLittle { + fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; +} + +impl TooLittle for () { + fn come_on_a_little_more_effort() {} + //~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 +} + +trait Lifetimes { + fn early<'early, T>(x: &'early T) -> impl Sized; +} + +impl Lifetimes for () { + fn early<'late, T>(_: &'late ()) {} + //~^ ERROR method `early` has an incompatible type for trait +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr new file mode 100644 index 0000000000000..2b32c52c829ec --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr @@ -0,0 +1,84 @@ +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:11:15 + | +LL | fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: type in trait + --> $DIR/method-signature-matches.rs:7:15 + | +LL | fn owo(x: ()) -> impl Sized; + | ^^ + = note: expected fn pointer `fn(())` + found fn pointer `fn(u8)` + +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:20:21 + | +LL | async fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, found opaque type +note: type in trait + --> $DIR/method-signature-matches.rs:16:21 + | +LL | async fn owo(x: ()) {} + | ^^ + = note: expected fn pointer `fn(()) -> _` + found fn pointer `fn(u8) -> _` + +error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 + --> $DIR/method-signature-matches.rs:29:28 + | +LL | fn calm_down_please() -> impl Sized; + | ------------------------------------ trait requires 0 parameters +... +LL | fn calm_down_please(_: (), _: (), _: ()) {} + | ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3 + +error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 + --> $DIR/method-signature-matches.rs:38:5 + | +LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; + | ---------------- trait requires 3 parameters +... +LL | fn come_on_a_little_more_effort() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0 + +error[E0053]: method `early` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:47:27 + | +LL | fn early<'late, T>(_: &'late ()) {} + | - ^^^^^^^^^ + | | | + | | expected type parameter `T`, found `()` + | | help: change the parameter type to match the trait: `&'early T` + | this type parameter + | +note: type in trait + --> $DIR/method-signature-matches.rs:43:28 + | +LL | fn early<'early, T>(x: &'early T) -> impl Sized; + | ^^^^^^^^^ + = note: expected fn pointer `fn(&'early T)` + found fn pointer `fn(&())` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0050, E0053. +For more information about an error, try `rustc --explain E0050`. From ed6a7cc22815e45cd0418b0b2b28b22238d9e81e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 9 Nov 2022 18:47:39 +0000 Subject: [PATCH 04/12] Remove save_and_restore_in_snapshot_flag --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 26 ---------- .../src/traits/specialize/mod.rs | 50 +++++++++---------- 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c2e1a79984699..c6bd771fad256 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -765,7 +765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expect_args = self .fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new(self); + let ocx = ObligationCtxt::new_in_snapshot(self); // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index ccba197dc80b7..fd3b3e4d59fa6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -778,32 +778,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - /// Clear the "currently in a snapshot" flag, invoke the closure, - /// then restore the flag to its original value. This flag is a - /// debugging measure designed to detect cases where we start a - /// snapshot, create type variables, and register obligations - /// which may involve those type variables in the fulfillment cx, - /// potentially leaving "dangling type variables" behind. - /// In such cases, an assertion will fail when attempting to - /// register obligations, within a snapshot. Very useful, much - /// better than grovelling through megabytes of `RUSTC_LOG` output. - /// - /// HOWEVER, in some cases the flag is unhelpful. In particular, we - /// sometimes create a "mini-fulfilment-cx" in which we enroll - /// obligations. As long as this fulfillment cx is fully drained - /// before we return, this is not a problem, as there won't be any - /// escaping obligations in the main cx. In those cases, you can - /// use this function. - pub fn save_and_restore_in_snapshot_flag(&self, func: F) -> R - where - F: FnOnce(&Self) -> R, - { - let flag = self.in_snapshot.replace(false); - let result = func(self); - self.in_snapshot.set(flag); - result - } - fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { debug!("start_snapshot()"); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 43819b3f490b1..231a18f86eae7 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,10 +10,12 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; +use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; use rustc_data_structures::fx::FxIndexSet; @@ -200,36 +202,32 @@ fn fulfill_implication<'tcx>( return Err(()); }; + // Needs to be `in_snapshot` because this function is used to rebase + // substitutions, which may happen inside of a select within a probe. + let mut engine = >::new_in_snapshot(infcx.tcx); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) + engine.register_predicate_obligations(infcx, obligations.chain(more_obligations)); - infcx.save_and_restore_in_snapshot_flag(|infcx| { - let errors = traits::fully_solve_obligations(&infcx, obligations.chain(more_obligations)); - match &errors[..] { - [] => { - debug!( - "fulfill_implication: an impl for {:?} specializes {:?}", - source_trait, target_trait - ); + let errors = engine.select_all_or_error(infcx); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + source_trait, + target_trait, + errors, + param_env.caller_bounds() + ); + return Err(()); + } - // Now resolve the *substitution* we built for the target earlier, replacing - // the inference variables inside with whatever we got from fulfillment. - Ok(infcx.resolve_vars_if_possible(target_substs)) - } - errors => { - // no dice! - debug!( - "fulfill_implication: for impls on {:?} and {:?}, \ - could not fulfill: {:?} given {:?}", - source_trait, - target_trait, - errors, - param_env.caller_bounds() - ); - Err(()) - } - } - }) + debug!("fulfill_implication: an impl for {:?} specializes {:?}", source_trait, target_trait); + + // Now resolve the *substitution* we built for the target earlier, replacing + // the inference variables inside with whatever we got from fulfillment. + Ok(infcx.resolve_vars_if_possible(target_substs)) } // Query provider for `specialization_graph_of`. From 63217e08cc041d0c4ce6df4e981899bfbc557de5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 9 Nov 2022 18:46:57 +0000 Subject: [PATCH 05/12] make dropck_outlives into a proper canonicalized type query --- compiler/rustc_traits/src/dropck_outlives.rs | 207 +++++++++---------- 1 file changed, 97 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index d5a8ca5ea784a..7b4ad9fea137a 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::query::Providers; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives; use rustc_trait_selection::traits::query::dropck_outlives::{ DropckConstraint, DropckOutlivesResult, }; use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; -use rustc_trait_selection::traits::{ - Normalized, ObligationCause, TraitEngine, TraitEngineExt as _, -}; +use rustc_trait_selection::traits::{Normalized, ObligationCause}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p }; @@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> { debug!("dropck_outlives(goal={:#?})", canonical_goal); - let (ref infcx, goal, canonical_inference_vars) = - tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal); - let tcx = infcx.tcx; - let ParamEnvAnd { param_env, value: for_ty } = goal; - - let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] }; - - // A stack of types left to process. Each round, we pop - // something from the stack and invoke - // `dtorck_constraint_for_ty`. This may produce new types that - // have to be pushed on the stack. This continues until we have explored - // all the reachable types from the type `for_ty`. - // - // Example: Imagine that we have the following code: - // - // ```rust - // struct A { - // value: B, - // children: Vec, - // } - // - // struct B { - // value: u32 - // } - // - // fn f() { - // let a: A = ...; - // .. - // } // here, `a` is dropped - // ``` - // - // at the point where `a` is dropped, we need to figure out - // which types inside of `a` contain region data that may be - // accessed by any destructors in `a`. We begin by pushing `A` - // onto the stack, as that is the type of `a`. We will then - // invoke `dtorck_constraint_for_ty` which will expand `A` - // into the types of its fields `(B, Vec)`. These will get - // pushed onto the stack. Eventually, expanding `Vec` will - // lead to us trying to push `A` a second time -- to prevent - // infinite recursion, we notice that `A` was already pushed - // once and stop. - let mut ty_stack = vec![(for_ty, 0)]; - - // Set used to detect infinite recursion. - let mut ty_set = FxHashSet::default(); - - let mut fulfill_cx = >::new(infcx.tcx); - - let cause = ObligationCause::dummy(); - let mut constraints = DropckConstraint::empty(); - while let Some((ty, depth)) = ty_stack.pop() { - debug!( - "{} kinds, {} overflows, {} ty_stack", - result.kinds.len(), - result.overflows.len(), - ty_stack.len() - ); - dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; - - // "outlives" represent types/regions that may be touched - // by a destructor. - result.kinds.append(&mut constraints.outlives); - result.overflows.append(&mut constraints.overflows); - - // If we have even one overflow, we should stop trying to evaluate further -- - // chances are, the subsequent overflows for this evaluation won't provide useful - // information and will just decrease the speed at which we can emit these errors - // (since we'll be printing for just that much longer for the often enormous types - // that result here). - if !result.overflows.is_empty() { - break; - } + tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| { + let tcx = ocx.infcx.tcx; + let ParamEnvAnd { param_env, value: for_ty } = goal; + + let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] }; + + // A stack of types left to process. Each round, we pop + // something from the stack and invoke + // `dtorck_constraint_for_ty`. This may produce new types that + // have to be pushed on the stack. This continues until we have explored + // all the reachable types from the type `for_ty`. + // + // Example: Imagine that we have the following code: + // + // ```rust + // struct A { + // value: B, + // children: Vec, + // } + // + // struct B { + // value: u32 + // } + // + // fn f() { + // let a: A = ...; + // .. + // } // here, `a` is dropped + // ``` + // + // at the point where `a` is dropped, we need to figure out + // which types inside of `a` contain region data that may be + // accessed by any destructors in `a`. We begin by pushing `A` + // onto the stack, as that is the type of `a`. We will then + // invoke `dtorck_constraint_for_ty` which will expand `A` + // into the types of its fields `(B, Vec)`. These will get + // pushed onto the stack. Eventually, expanding `Vec` will + // lead to us trying to push `A` a second time -- to prevent + // infinite recursion, we notice that `A` was already pushed + // once and stop. + let mut ty_stack = vec![(for_ty, 0)]; + + // Set used to detect infinite recursion. + let mut ty_set = FxHashSet::default(); + + let cause = ObligationCause::dummy(); + let mut constraints = DropckConstraint::empty(); + while let Some((ty, depth)) = ty_stack.pop() { + debug!( + "{} kinds, {} overflows, {} ty_stack", + result.kinds.len(), + result.overflows.len(), + ty_stack.len() + ); + dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; + + // "outlives" represent types/regions that may be touched + // by a destructor. + result.kinds.append(&mut constraints.outlives); + result.overflows.append(&mut constraints.overflows); + + // If we have even one overflow, we should stop trying to evaluate further -- + // chances are, the subsequent overflows for this evaluation won't provide useful + // information and will just decrease the speed at which we can emit these errors + // (since we'll be printing for just that much longer for the often enormous types + // that result here). + if !result.overflows.is_empty() { + break; + } - // dtorck types are "types that will get dropped but which - // do not themselves define a destructor", more or less. We have - // to push them onto the stack to be expanded. - for ty in constraints.dtorck_types.drain(..) { - match infcx.at(&cause, param_env).normalize(ty) { - Ok(Normalized { value: ty, obligations }) => { - fulfill_cx.register_predicate_obligations(infcx, obligations); - - debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); - - match ty.kind() { - // All parameters live for the duration of the - // function. - ty::Param(..) => {} - - // A projection that we couldn't resolve - it - // might have a destructor. - ty::Projection(..) | ty::Opaque(..) => { - result.kinds.push(ty.into()); - } + // dtorck types are "types that will get dropped but which + // do not themselves define a destructor", more or less. We have + // to push them onto the stack to be expanded. + for ty in constraints.dtorck_types.drain(..) { + let Normalized { value: ty, obligations } = + ocx.infcx.at(&cause, param_env).normalize(ty)?; + ocx.register_obligations(obligations); + + debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + + match ty.kind() { + // All parameters live for the duration of the + // function. + ty::Param(..) => {} + + // A projection that we couldn't resolve - it + // might have a destructor. + ty::Projection(..) | ty::Opaque(..) => { + result.kinds.push(ty.into()); + } - _ => { - if ty_set.insert(ty) { - ty_stack.push((ty, depth + 1)); - } + _ => { + if ty_set.insert(ty) { + ty_stack.push((ty, depth + 1)); } } } - - // We don't actually expect to fail to normalize. - // That implies a WF error somewhere else. - Err(NoSolution) => { - return Err(NoSolution); - } } } - } - - debug!("dropck_outlives: result = {:#?}", result); - infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx) + debug!("dropck_outlives: result = {:#?}", result); + Ok(result) + }) } /// Returns a set of constraints that needs to be satisfied in From 0f3ae6218ef1d9e9b14bf983b463785b14abc205 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 10 Nov 2022 16:51:14 -0700 Subject: [PATCH 06/12] rustdoc: use checkbox instead of switch for settings toggles The switch is designed to give the application a "physical" feel, but nothing else in here really followed through. They didn't support the "flick" gesture that real iOS switches support, and the radio buttons that were also used in Rustdoc Settings were a more "classic" form element anyway. Also, while "switches" are the exclusive toggle design on iOS (since [Apple HIG] reserves checkboxes for Mac only), the [Google Material] guidelines say that lists of switches are bad, and you should just use check boxes. [Apple HIG]: https://developer.apple.com/design/human-interface-guidelines/components/selection-and-input/toggles [Google Material]: https://m3.material.io/components/checkbox/guidelines#6902f23d-ceba-4b19-ae3b-b78b9b01d185 --- src/librustdoc/html/static/css/settings.css | 57 +++++++------------ src/librustdoc/html/static/css/themes/ayu.css | 10 ---- .../html/static/css/themes/dark.css | 10 ---- .../html/static/css/themes/light.css | 9 --- src/librustdoc/html/static/js/settings.js | 4 +- .../docblock-code-block-line-number.goml | 4 +- src/test/rustdoc-gui/settings.goml | 9 +-- 7 files changed, 25 insertions(+), 78 deletions(-) diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 83939f63b4e85..1f6fb961e918d 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -8,7 +8,8 @@ flex-wrap: wrap; } -.setting-line .radio-line input { +.setting-line .radio-line input, +.setting-line .toggle input { margin-right: 0.3em; height: 1.2rem; width: 1.2rem; @@ -17,9 +18,18 @@ outline: none; -webkit-appearance: none; cursor: pointer; +} +.setting-line .radio-line input { border-radius: 50%; } -.setting-line .radio-line input + span { +.setting-line .toggle input:checked { + content: url('data:image/svg+xml,\ + \ + '); +} + +.setting-line .radio-line input + span, +.setting-line .toggle span { padding-bottom: 1px; } @@ -49,37 +59,6 @@ cursor: pointer; } -.toggle input { - opacity: 0; - position: absolute; -} - -.slider { - position: relative; - width: 45px; - min-width: 45px; - display: block; - height: 28px; - margin-right: 20px; - cursor: pointer; - background-color: #ccc; - transition: .3s; -} - -.slider:before { - position: absolute; - content: ""; - height: 19px; - width: 19px; - left: 4px; - bottom: 4px; - transition: .3s; -} - -input:checked + .slider:before { - transform: translateX(19px); -} - .setting-line > .sub-settings { padding-left: 42px; width: 100%; @@ -94,7 +73,11 @@ input:checked + .slider:before { box-shadow: inset 0 0 0 3px var(--main-background-color); background-color: var(--settings-input-color); } -.setting-line .radio-line input:focus { +.setting-line .toggle input:checked { + background-color: var(--settings-input-color); +} +.setting-line .radio-line input:focus, +.setting-line .toggle input:focus { box-shadow: 0 0 1px 1px var(--settings-input-color); } /* In here we combine both `:focus` and `:checked` properties. */ @@ -102,9 +85,7 @@ input:checked + .slider:before { box-shadow: inset 0 0 0 3px var(--main-background-color), 0 0 2px 2px var(--settings-input-color); } -.setting-line .radio-line input:hover { +.setting-line .radio-line input:hover, +.setting-line .toggle input:hover { border-color: var(--settings-input-color) !important; } -input:checked + .slider { - background-color: var(--settings-input-color); -} diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 129ef6e10e7e7..63c0b78b2371c 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -75,16 +75,6 @@ Original by Dempfi (https://github.com/dempfi/ayu) --crate-search-hover-border: #e0e0e0; } -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); -} - h1, h2, h3, h4 { color: white; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 7cd2d7817d59d..77f888330a42a 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -70,16 +70,6 @@ --crate-search-hover-border: #2196f3; } -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); -} - .content .item-info::before { color: #ccc; } body.source .example-wrap pre.rust a { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index c41ec24884127..13ad38cf6e631 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -67,15 +67,6 @@ --crate-search-hover-border: #717171; } -.slider { - background-color: #ccc; -} -.slider:before { - background-color: white; -} -input:focus + .slider { - box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); -} .content .item-info::before { color: #ccc; } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 141563bd46a19..95cc265f1bdf6 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -66,8 +66,7 @@ function setEvents(settingsElement) { updateLightAndDark(); - onEachLazy(settingsElement.getElementsByClassName("slider"), elem => { - const toggle = elem.previousElementSibling; + onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => { const settingId = toggle.id; const settingValue = getSettingValue(settingId); if (settingValue !== null) { @@ -139,7 +138,6 @@ const checked = setting["default"] === true ? " checked" : ""; output += ``; } diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index 911ee34be94e5..fec21ad35c3eb 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -30,10 +30,10 @@ wait-for: "#settings" assert-css: ("#settings", {"display": "block"}) // Then, click the toggle button. -click: "input#line-numbers + .slider" +click: "input#line-numbers" wait-for: 100 // wait-for-false does not exist assert-false: "pre.example-line-numbers" // Finally, turn it on again. -click: "input#line-numbers + .slider" +click: "input#line-numbers" wait-for: "pre.example-line-numbers" diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index f258f4d2a838e..a800cfc82d4c9 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -118,7 +118,7 @@ assert: ".setting-line.hidden #theme" assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme") assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme") -// We now check that clicking on the "sliders"' text is like clicking on the slider. +// We now check that clicking on the toggles' text is like clicking on the checkbox. // To test it, we use the "Disable keyboard shortcuts". local-storage: {"rustdoc-disable-shortcuts": "false"} click: ".setting-line:last-child .toggle .label" @@ -141,10 +141,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"}) // Now we go to the settings page to check that the CSS is loaded as expected. goto: "file://" + |DOC_PATH| + "/settings.html" wait-for: "#settings" -assert-css: ( - ".setting-line .toggle .slider", - {"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"}, -) +assert-css: (".setting-line", {"position": "relative"}) assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS) compare-elements-position: (".sub form", "#settings", ("x")) @@ -162,4 +159,4 @@ reload: size: (300, 1000) click: "#settings-menu" wait-for: "#settings" -assert-css: ("#settings .slider", {"width": "45px"}, ALL) +assert-css: (".setting-line", {"position": "relative"}) From 014f7f4092da54315c4f4a781f2e8879a2372120 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Nov 2022 17:06:41 +0000 Subject: [PATCH 07/12] Remove some redundant arguments --- .../src/annotate_snippet_emitter_writer.rs | 1 - compiler/rustc_errors/src/emitter.rs | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f14b8ee3254f3..c450c276366e1 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter { let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.source_map, &mut primary_span, &mut children, &diag.level, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b7b8fe3f25a04..94df0c03b954e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -314,7 +314,6 @@ pub trait Emitter: Translate { fn fix_multispans_in_extern_macros_and_render_macro_backtrace( &self, - source_map: &Option>, span: &mut MultiSpan, children: &mut Vec, level: &Level, @@ -340,7 +339,7 @@ pub trait Emitter: Translate { .collect(); if !backtrace { - self.fix_multispans_in_extern_macros(source_map, span, children); + self.fix_multispans_in_extern_macros(span, children); } self.render_multispans_macro_backtrace(span, children, backtrace); @@ -480,15 +479,13 @@ pub trait Emitter: Translate { // this will change the span to point at the use site. fn fix_multispans_in_extern_macros( &self, - source_map: &Option>, span: &mut MultiSpan, children: &mut Vec, ) { - let Some(source_map) = source_map else { return }; debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); - self.fix_multispan_in_extern_macros(source_map, span); + self.fix_multispan_in_extern_macros(span); for child in children.iter_mut() { - self.fix_multispan_in_extern_macros(source_map, &mut child.span); + self.fix_multispan_in_extern_macros(&mut child.span); } debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } @@ -496,7 +493,8 @@ pub trait Emitter: Translate { // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. // Since these locations are often difficult to read, // we move these spans from the external macros to their corresponding use site. - fn fix_multispan_in_extern_macros(&self, source_map: &Lrc, span: &mut MultiSpan) { + fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) { + let Some(source_map) = self.source_map() else { return }; // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() @@ -544,7 +542,6 @@ impl Emitter for EmitterWriter { debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &self.sm, &mut primary_span, &mut children, &diag.level, From 21ce58732bc70a1696e31219ca5f2c0c25860798 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Nov 2022 14:45:18 +0000 Subject: [PATCH 08/12] Don't add message that will never be shown to users It will still be used in json, as seen by the ui test changes --- .../src/traits/error_reporting/suggestions.rs | 4 ++-- src/test/ui/iterators/collect-into-array.rs | 1 - src/test/ui/iterators/collect-into-array.stderr | 2 +- src/test/ui/iterators/collect-into-slice.rs | 2 -- src/test/ui/iterators/collect-into-slice.stderr | 6 +++--- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index aece4ab792285..02e880a8e6e95 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { (Ok(l), Ok(r)) => l.line == r.line, _ => true, }; - if !ident.span.overlaps(span) && !same_line { + if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line { multispan.push_span_label(ident.span, "required by a bound in this"); } } let descr = format!("required by a bound in `{}`", item_name); - if span != DUMMY_SP { + if !span.is_dummy() { let msg = format!("required by this bound in `{}`", item_name); multispan.push_span_label(span, msg); err.span_note(multispan, &descr); diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs index 7d35da825328e..4c424999b754d 100644 --- a/src/test/ui/iterators/collect-into-array.rs +++ b/src/test/ui/iterators/collect-into-array.rs @@ -1,5 +1,4 @@ fn main() { - //~^ NOTE required by a bound in this let whatever: [u32; 10] = (0..10).collect(); //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr index 7fe9707e6d232..a23a36a88abb3 100644 --- a/src/test/ui/iterators/collect-into-array.stderr +++ b/src/test/ui/iterators/collect-into-array.stderr @@ -1,5 +1,5 @@ error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator - --> $DIR/collect-into-array.rs:3:31 + --> $DIR/collect-into-array.rs:2:31 | LL | let whatever: [u32; 10] = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs index 5eade075613fe..09832c260d04e 100644 --- a/src/test/ui/iterators/collect-into-slice.rs +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -1,6 +1,4 @@ fn process_slice(data: &[i32]) { - //~^ NOTE required by a bound in this - //~| NOTE required by a bound in this todo!() } diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr index bce40118bdfa0..bc152467ce3a5 100644 --- a/src/test/ui/iterators/collect-into-slice.stderr +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:9 + --> $DIR/collect-into-slice.rs:6:9 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,7 +9,7 @@ LL | let some_generated_vec = (0..10).collect(); = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/collect-into-slice.rs:8:38 + --> $DIR/collect-into-slice.rs:6:38 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time @@ -22,7 +22,7 @@ LL | fn collect>(self) -> B | ^ required by this bound in `collect` error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size - --> $DIR/collect-into-slice.rs:8:30 + --> $DIR/collect-into-slice.rs:6:30 | LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ ------- required by a bound introduced by this call From df2adc4760a1c03096ab4b39512ba90b983c2332 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 4 Nov 2022 16:04:47 +0000 Subject: [PATCH 09/12] Print all labels, even if they have no span. Fall back to main item's span. --- .../locales/en-US/passes.ftl | 5 +- compiler/rustc_errors/src/emitter.rs | 47 ++++++++++++---- compiler/rustc_passes/src/check_attr.rs | 55 ++++++++++++++----- compiler/rustc_passes/src/errors.rs | 3 + compiler/rustc_resolve/src/diagnostics.rs | 10 ++-- .../rustc_resolve/src/late/diagnostics.rs | 18 +++--- src/test/ui/asm/naked-invalid-attr.stderr | 2 +- ...43106-gating-of-builtin-attrs-error.stderr | 6 +- .../issue-43106-gating-of-builtin-attrs.rs | 2 +- ...issue-43106-gating-of-builtin-attrs.stderr | 8 +-- .../issue-69396-const-no-type-in-macro.stderr | 5 +- 11 files changed, 110 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 5239ff9dc0571..001e53d1d0e4c 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -47,7 +47,10 @@ passes_no_coverage_not_coverable = passes_should_be_applied_to_fn = attribute should be applied to a function definition - .label = not a function definition + .label = {$on_crate -> + [true] cannot be applied to crates + *[false] not a function definition + } passes_naked_tracked_caller = cannot use `#[track_caller]` with `#[naked]` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 94df0c03b954e..55c7997a51363 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2210,22 +2210,45 @@ impl FileWithAnnotatedLines { if let Some(ref sm) = emitter.source_map() { for span_label in msp.span_labels() { + let fixup_lo_hi = |span: Span| { + let lo = sm.lookup_char_pos(span.lo()); + let mut hi = sm.lookup_char_pos(span.hi()); + + // Watch out for "empty spans". If we get a span like 6..6, we + // want to just display a `^` at 6, so convert that to + // 6..7. This is degenerate input, but it's best to degrade + // gracefully -- and the parser likes to supply a span like + // that for EOF, in particular. + + if lo.col_display == hi.col_display && lo.line == hi.line { + hi.col_display += 1; + } + (lo, hi) + }; + if span_label.span.is_dummy() { + if let Some(span) = msp.primary_span() { + // if we don't know where to render the annotation, emit it as a note + // on the primary span. + + let (lo, hi) = fixup_lo_hi(span); + + let ann = Annotation { + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label + .label + .as_ref() + .map(|m| emitter.translate_message(m, args).to_string()), + annotation_type: AnnotationType::Singleline, + }; + add_annotation_to_file(&mut output, lo.file, lo.line, ann); + } continue; } - let lo = sm.lookup_char_pos(span_label.span.lo()); - let mut hi = sm.lookup_char_pos(span_label.span.hi()); - - // Watch out for "empty spans". If we get a span like 6..6, we - // want to just display a `^` at 6, so convert that to - // 6..7. This is degenerate input, but it's best to degrade - // gracefully -- and the parser likes to supply a span like - // that for EOF, in particular. - - if lo.col_display == hi.col_display && lo.line == hi.line { - hi.col_display += 1; - } + let (lo, hi) = fixup_lo_hi(span_label.span); if lo.line != hi.line { let ml = MultilineAnnotation { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 27a57adf964a3..0c34b0e1bf3f9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> { } sym::naked => self.check_naked(hir_id, attr, span, target), sym::rustc_legacy_const_generics => { - self.check_rustc_legacy_const_generics(&attr, span, target, item) + self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item) } sym::rustc_lint_query_instability => { - self.check_rustc_lint_query_instability(&attr, span, target) + self.check_rustc_lint_query_instability(hir_id, &attr, span, target) } sym::rustc_lint_diagnostics => { - self.check_rustc_lint_diagnostics(&attr, span, target) + self.check_rustc_lint_diagnostics(hir_id, &attr, span, target) } sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target), sym::rustc_lint_opt_deny_field_access => { @@ -135,7 +135,9 @@ impl CheckAttrVisitor<'_> { | sym::rustc_dirty | sym::rustc_if_this_changed | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), - sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target), + sym::cmse_nonsecure_entry => { + self.check_cmse_nonsecure_entry(hir_id, attr, span, target) + } sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), sym::const_trait => self.check_const_trait(attr, span, target), sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), @@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> { } /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. - fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_cmse_nonsecure_entry( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, @@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span }); + self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation { + attr_span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); false } } @@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -1240,7 +1253,7 @@ impl CheckAttrVisitor<'_> { UNUSED_ATTRIBUTES, hir_id, attr.span, - errors::Cold { span }, + errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID }, ); } } @@ -1376,6 +1389,7 @@ impl CheckAttrVisitor<'_> { /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, @@ -1386,6 +1400,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); return false; } @@ -1450,12 +1465,19 @@ impl CheckAttrVisitor<'_> { /// Helper function for checking that the provided attribute is only applied to a function or /// method. - fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_applied_to_fn_or_method( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } else { @@ -1467,17 +1489,24 @@ impl CheckAttrVisitor<'_> { /// or method. fn check_rustc_lint_query_instability( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, ) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or /// method. - fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + fn check_rustc_lint_diagnostics( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1dbf0d642e2af..c6cd69add28a0 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -81,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -97,6 +98,7 @@ pub struct TrackedCallerWrongLocation { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -367,6 +369,7 @@ pub struct MustNotSuspend { pub struct Cold { #[label] pub span: Span, + pub on_crate: bool, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7961e3f1194e1..a12918b297990 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -241,10 +241,12 @@ impl<'a> Resolver<'a> { )); err.span_label(span, format!("`{}` re{} here", name, new_participle)); - err.span_label( - self.session.source_map().guess_head_span(old_binding.span), - format!("previous {} of the {} `{}` here", old_noun, old_kind, name), - ); + if !old_binding.span.is_dummy() && old_binding.span != span { + err.span_label( + self.session.source_map().guess_head_span(old_binding.span), + format!("previous {} of the {} `{}` here", old_noun, old_kind, name), + ); + } // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a1338dcd4771b..346024bb5984b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -806,14 +806,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.code(rustc_errors::error_code!(E0411)); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); + if !item_kind.ident.span.is_dummy() { + err.span_label( + item_kind.ident.span, + format!( + "`Self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); + } } true } diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr index 58344be93346d..e8ddccc854abe 100644 --- a/src/test/ui/asm/naked-invalid-attr.stderr +++ b/src/test/ui/asm/naked-invalid-attr.stderr @@ -36,7 +36,7 @@ error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:5:1 | LL | #![naked] - | ^^^^^^^^^ + | ^^^^^^^^^ cannot be applied to crates error: aborting due to 5 previous errors diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 5a645cf4ef987..7876704042188 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 | LL | #![no_link] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ not an `extern crate` item error: attribute should be applied to a free function, impl method or static --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1 | LL | #![export_name = "2200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1 | LL | #![inline] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not a function or closure error: `macro_export` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 8db12e55d25c2..1fa315f3d2159 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -1,6 +1,6 @@ //~ NOTE not a function //~| NOTE not a foreign function or static -//~| NOTE not a function or static +//~| NOTE cannot be applied to crates //~| NOTE not an `extern` block // This test enumerates as many compiler-builtin ungated attributes as // possible (that is, all the mutually compatible ones), and checks diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 310d1f720eb7c..30039267979fb 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 | LL | #![cold] - | ^^^^^^^^ + | ^^^^^^^^ cannot be applied to crates | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 | LL | #![link()] - | ^^^^^^^^^^ + | ^^^^^^^^^^ not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 | LL | #![link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 | LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr index f581429a28154..89aeafebac497 100644 --- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13 | LL | const A = "A".$fn(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | `A` redefined here - | previous definition of the value `A` here + | ^^^^^^^^^^^^^^^^^^^^ `A` redefined here ... LL | / suite! { LL | | len; From 269dad27f23e85359afee82f8fbd144fec616dc9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 11 Nov 2022 09:57:58 -0700 Subject: [PATCH 10/12] rustdoc: add test cases for checkbox toggles --- src/test/rustdoc-gui/settings.goml | 83 ++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index a800cfc82d4c9..7e7971d47fbca 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -48,7 +48,8 @@ assert: ".setting-line.hidden #preferred-light-theme" assert-property: ("#theme .choices #theme-dark", {"checked": "true"}) // Some style checks... -// First we check the "default" display. +move-cursor-to: "#settings-menu > a" +// First we check the "default" display for radio buttons. assert-css: ( "#theme-dark", { @@ -57,7 +58,7 @@ assert-css: ( }, ) assert-css: ("#theme-light", {"border-color": "rgb(221, 221, 221)", "box-shadow": "none"}) -// Let's start with the hover. +// Let's start with the hover for radio buttons. move-cursor-to: "#theme-dark" assert-css: ( "#theme-dark", @@ -69,7 +70,7 @@ assert-css: ( move-cursor-to: "#theme-light" assert-css: ("#theme-light", {"border-color": "rgb(33, 150, 243)", "box-shadow": "none"}) move-cursor-to: "#theme-ayu" -// Let's now check with the focus. +// Let's now check with the focus for radio buttons. focus: "#theme-dark" assert-css: ( "#theme-dark", @@ -86,7 +87,7 @@ assert-css: ( "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", }, ) -// Now we check we both focus and hover. +// Now we check we both focus and hover for radio buttons. move-cursor-to: "#theme-dark" focus: "#theme-dark" assert-css: ( @@ -106,6 +107,80 @@ assert-css: ( }, ) +// First we check the "default" display for toggles. +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(221, 221, 221)", + }, +) +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(221, 221, 221)", + } +) +// Let's start with the hover for toggles. +move-cursor-to: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(33, 150, 243)", + }, +) +move-cursor-to: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(33, 150, 243)", + } +) +move-cursor-to: "#settings-menu > a" +// Let's now check with the focus for toggles. +focus: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(221, 221, 221)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +focus: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(221, 221, 221)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +// Now we check we both focus and hover for toggles. +move-cursor-to: "#auto-hide-large-items" +focus: "#auto-hide-large-items" +assert-css: ( + "#auto-hide-large-items", + { + "background-color": "rgb(33, 150, 243)", + "border-color": "rgb(33, 150, 243)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) +move-cursor-to: "#use-system-theme" +focus: "#use-system-theme" +assert-css: ( + "#use-system-theme", + { + "background-color": "rgba(0, 0, 0, 0)", + "border-color": "rgb(33, 150, 243)", + "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", + }, +) + // We now switch the display. click: "#use-system-theme" // Wait for the hidden element to show up. From 934c4141cc56bda1f46d508df71d1ed8524fb915 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 11 Nov 2022 22:07:29 +0000 Subject: [PATCH 11/12] Update cargo 9 commits in 9286a1beba5b28b115bad67de2ae91fb1c61eb0b..a3dfea71ca0c888a88111086898aa833c291d497 2022-11-04 06:41:49 +0000 to 2022-11-11 03:50:47 +0000 - fix: return non UTF-8 error message (rust-lang/cargo#11321) - Extract `two_kinds_of_msg_format_err` message to de-duplicate it (rust-lang/cargo#11358) - Propagate change of artifact bin dep to its parent fingerprint (rust-lang/cargo#11353) - Fix not a hyperlink warnings (rust-lang/cargo#11357) - Fix wait-for-publish with sparse registry (rust-lang/cargo#11356) - Add `rm` alias to configuration docs (rust-lang/cargo#11351) - Add `registries.crates-io.protocol` docs (rust-lang/cargo#11350) - test(features2): test to prevent regressing of optional host deps of dep (rust-lang/cargo#11342) - Bump to 0.68.0, update changelog (rust-lang/cargo#11340) --- Cargo.lock | 2 +- src/tools/cargo | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddacf9cf02463..c105d04c1f440 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,7 +273,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.67.0" +version = "0.68.0" dependencies = [ "anyhow", "atty", diff --git a/src/tools/cargo b/src/tools/cargo index 9286a1beba5b2..a3dfea71ca0c8 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9286a1beba5b28b115bad67de2ae91fb1c61eb0b +Subproject commit a3dfea71ca0c888a88111086898aa833c291d497 From 7e86b846bfbf9587e50b87c4f6a0950adbccb9a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 11 Nov 2022 22:16:14 +0000 Subject: [PATCH 12/12] UI tests can be assigned to T-compiler --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index d3f9efcc41c3e..8efd9af41a42d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -573,6 +573,7 @@ fallback = [ "/src/llvm-project" = ["@cuviper"] "/src/rustdoc-json-types" = ["rustdoc"] "/src/stage0.json" = ["bootstrap"] +"/src/test/ui" = ["compiler"] "/src/tools/cargo" = ["@ehuss", "@joshtriplett"] "/src/tools/compiletest" = ["bootstrap"] "/src/tools/linkchecker" = ["@ehuss"]