From 22aa104bce457e7d70b05d7a32cdf09f25ac06b1 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 2 Aug 2024 00:28:57 +0800 Subject: [PATCH 01/12] don't suggest turning crate-level attributes into outer style --- compiler/rustc_ast/src/ast.rs | 11 ++++++ compiler/rustc_parse/src/parser/attr.rs | 38 +++++++++++++------ compiler/rustc_parse/src/parser/stmt.rs | 5 +++ tests/ui/delegation/inner-attr.stderr | 5 --- .../attribute/attr-stmt-expr-attr-bad.stderr | 15 -------- tests/ui/parser/attribute/attr.stderr | 5 --- .../inner-attr-after-doc-comment.stderr | 5 --- tests/ui/parser/inner-attr.stderr | 5 --- .../isgg-invalid-outer-attttr-issue-127930.rs | 10 +++++ ...g-invalid-outer-attttr-issue-127930.stderr | 12 ++++++ tests/ui/parser/issues/issue-30318.fixed | 2 +- tests/ui/parser/issues/issue-30318.rs | 2 +- tests/ui/parser/issues/issue-30318.stderr | 8 ++-- 13 files changed, 70 insertions(+), 53 deletions(-) create mode 100644 tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs create mode 100644 tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fc1af3fc3dd11..0c81c0f4c93e1 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2898,6 +2898,17 @@ pub struct AttrItem { pub tokens: Option, } +impl AttrItem { + pub fn is_valid_for_outer_style(&self) -> bool { + self.path == sym::cfg_attr + || self.path == sym::cfg + || self.path == sym::forbid + || self.path == sym::warn + || self.path == sym::allow + || self.path == sym::deny + } +} + /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 12b9414d1f760..7b64a60960b5e 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -67,6 +67,7 @@ impl<'a> Parser<'a> { token::CommentKind::Line => OuterAttributeType::DocComment, token::CommentKind::Block => OuterAttributeType::DocBlockComment, }, + true, ) { err.note(fluent::parse_note); err.span_suggestion_verbose( @@ -130,7 +131,11 @@ impl<'a> Parser<'a> { // Emit error if inner attribute is encountered and forbidden. if style == ast::AttrStyle::Inner { - this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); + this.error_on_forbidden_inner_attr( + attr_sp, + inner_parse_policy, + item.is_valid_for_outer_style(), + ); } Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp)) @@ -142,6 +147,7 @@ impl<'a> Parser<'a> { err: &mut Diag<'_>, span: Span, attr_type: OuterAttributeType, + suggest_to_outer: bool, ) -> Option { let mut snapshot = self.create_snapshot_for_diagnostic(); let lo = span.lo() @@ -176,16 +182,18 @@ impl<'a> Parser<'a> { // FIXME(#100717) err.arg("item", item.kind.descr()); err.span_label(item.span, fluent::parse_label_does_not_annotate_this); - err.span_suggestion_verbose( - replacement_span, - fluent::parse_sugg_change_inner_to_outer, - match attr_type { - OuterAttributeType::Attribute => "", - OuterAttributeType::DocBlockComment => "*", - OuterAttributeType::DocComment => "/", - }, - rustc_errors::Applicability::MachineApplicable, - ); + if suggest_to_outer { + err.span_suggestion_verbose( + replacement_span, + fluent::parse_sugg_change_inner_to_outer, + match attr_type { + OuterAttributeType::Attribute => "", + OuterAttributeType::DocBlockComment => "*", + OuterAttributeType::DocComment => "/", + }, + rustc_errors::Applicability::MachineApplicable, + ); + } return None; } Err(item_err) => { @@ -196,7 +204,12 @@ impl<'a> Parser<'a> { Some(replacement_span) } - pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy) { + pub(super) fn error_on_forbidden_inner_attr( + &self, + attr_sp: Span, + policy: InnerAttrPolicy, + suggest_to_outer: bool, + ) { if let InnerAttrPolicy::Forbidden(reason) = policy { let mut diag = match reason.as_ref().copied() { Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => { @@ -230,6 +243,7 @@ impl<'a> Parser<'a> { &mut diag, attr_sp, OuterAttributeType::Attribute, + suggest_to_outer, ) .is_some() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7b0daaa14335f..fe8fbeea4767e 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -439,11 +439,16 @@ impl<'a> Parser<'a> { pub fn parse_block(&mut self) -> PResult<'a, P> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { + let suggest_to_outer = match &last.kind { + ast::AttrKind::Normal(attr) => attr.item.is_valid_for_outer_style(), + _ => false, + }; self.error_on_forbidden_inner_attr( last.span, super::attr::InnerAttrPolicy::Forbidden(Some( InnerAttrForbiddenReason::InCodeBlock, )), + suggest_to_outer, ); } Ok(block) diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index f3b53e331ad88..257ab760ffc1a 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -8,11 +8,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - reuse a as b { #![rustc_dummy] self } -LL + reuse a as b { #[rustc_dummy] self } - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index 1ba130e20b578..bd860841b8060 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -359,11 +359,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); } - | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:77:32 @@ -375,11 +370,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; } - | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:79:32 @@ -391,11 +381,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | previous outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the item macro invocation, change the attribute from inner to outer style - | -LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } -LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; } - | error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:85:35 diff --git a/tests/ui/parser/attribute/attr.stderr b/tests/ui/parser/attribute/attr.stderr index 2e0b16efb6cea..a79a5246c2a9a 100644 --- a/tests/ui/parser/attribute/attr.stderr +++ b/tests/ui/parser/attribute/attr.stderr @@ -7,11 +7,6 @@ LL | fn foo() {} | ----------- the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![lang = "foo"] -LL + #[lang = "foo"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr-after-doc-comment.stderr b/tests/ui/parser/inner-attr-after-doc-comment.stderr index 6dbc0fd93fd42..f087c2e4d6540 100644 --- a/tests/ui/parser/inner-attr-after-doc-comment.stderr +++ b/tests/ui/parser/inner-attr-after-doc-comment.stderr @@ -13,11 +13,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![recursion_limit="100"] -LL + #[recursion_limit="100"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr index 57ca164fc15a2..18a82ea4c3856 100644 --- a/tests/ui/parser/inner-attr.stderr +++ b/tests/ui/parser/inner-attr.stderr @@ -10,11 +10,6 @@ LL | fn main() {} | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -help: to annotate the function, change the attribute from inner to outer style - | -LL - #![recursion_limit="100"] -LL + #[recursion_limit="100"] - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs new file mode 100644 index 0000000000000..26541a89a565a --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] +fn foo() {} + +#![feature(iter_array_chunks)] //~ ERROR an inner attribute is not permitted in this context +fn bar() {} + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr new file mode 100644 index 0000000000000..d6daa21e7418d --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr @@ -0,0 +1,12 @@ +error: an inner attribute is not permitted in this context + --> $DIR/isgg-invalid-outer-attttr-issue-127930.rs:4:1 + | +LL | #![feature(iter_array_chunks)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bar() {} + | ----------- the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/issue-30318.fixed b/tests/ui/parser/issues/issue-30318.fixed index d1661be519393..d4720834746fc 100644 --- a/tests/ui/parser/issues/issue-30318.fixed +++ b/tests/ui/parser/issues/issue-30318.fixed @@ -6,7 +6,7 @@ fn foo() { } //~^ ERROR expected outer doc comment fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function -#[test] //~ ERROR an inner attribute is not permitted in this context +#[cfg(test)] //~ ERROR an inner attribute is not permitted in this context fn baz() { } //~ NOTE the inner attribute doesn't annotate this function //~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually diff --git a/tests/ui/parser/issues/issue-30318.rs b/tests/ui/parser/issues/issue-30318.rs index 6f055cd4f7e95..0555379836ac9 100644 --- a/tests/ui/parser/issues/issue-30318.rs +++ b/tests/ui/parser/issues/issue-30318.rs @@ -6,7 +6,7 @@ fn foo() { } //~^ ERROR expected outer doc comment fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function -#![test] //~ ERROR an inner attribute is not permitted in this context +#![cfg(test)] //~ ERROR an inner attribute is not permitted in this context fn baz() { } //~ NOTE the inner attribute doesn't annotate this function //~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually diff --git a/tests/ui/parser/issues/issue-30318.stderr b/tests/ui/parser/issues/issue-30318.stderr index c441a92abad92..56bc200db1d3a 100644 --- a/tests/ui/parser/issues/issue-30318.stderr +++ b/tests/ui/parser/issues/issue-30318.stderr @@ -15,16 +15,16 @@ LL | /// Misplaced comment... error: an inner attribute is not permitted in this context --> $DIR/issue-30318.rs:9:1 | -LL | #![test] - | ^^^^^^^^ +LL | #![cfg(test)] + | ^^^^^^^^^^^^^ LL | fn baz() { } | ------------ the inner attribute doesn't annotate this function | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files help: to annotate the function, change the attribute from inner to outer style | -LL - #![test] -LL + #[test] +LL - #![cfg(test)] +LL + #[cfg(test)] | error[E0753]: expected outer doc comment From b335ec9ec8d1132efee4e900a1c173efc7f4a357 Mon Sep 17 00:00:00 2001 From: Flying-Toast <38232168+Flying-Toast@users.noreply.github.com> Date: Sat, 23 Mar 2024 10:49:05 -0400 Subject: [PATCH 02/12] Add a special case for CStr/CString in the improper_ctypes lint Instead of saying to "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct", we now tell users to "Use `*const ffi::c_char` instead, and pass the value from `CStr::as_ptr()`" when the type involved is a `CStr` or a `CString`. Co-authored-by: Jieyou Xu --- compiler/rustc_lint/messages.ftl | 5 ++ compiler/rustc_lint/src/types.rs | 54 ++++++++---- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/ffi/c_str.rs | 1 + ...extern-C-non-FFI-safe-arg-ice-52334.stderr | 12 +-- tests/ui/lint/lint-ctypes-cstr.rs | 36 ++++++++ tests/ui/lint/lint-ctypes-cstr.stderr | 84 +++++++++++++++++++ 7 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 tests/ui/lint/lint-ctypes-cstr.rs create mode 100644 tests/ui/lint/lint-ctypes-cstr.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7e4feb0a82716..52a03772dc23c 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -361,6 +361,11 @@ lint_improper_ctypes_box = box cannot be represented as a single pointer lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead lint_improper_ctypes_char_reason = the `char` type has no C equivalent + +lint_improper_ctypes_cstr_help = + consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout + lint_improper_ctypes_dyn = trait objects have no C equivalent lint_improper_ctypes_enum_repr_help = diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f3196cfed533e..d84d60ef5a7c1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -984,6 +984,14 @@ struct ImproperCTypesVisitor<'a, 'tcx> { mode: CItemKind, } +/// Accumulator for recursive ffi type checking +struct CTypesVisitorState<'tcx> { + cache: FxHashSet>, + /// The original type being checked, before we recursed + /// to any other types it contains. + base_ty: Ty<'tcx>, +} + enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), @@ -1212,7 +1220,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given field's type is "ffi-safe". fn check_field_type_for_ffi( &self, - cache: &mut FxHashSet>, + acc: &mut CTypesVisitorState<'tcx>, field: &ty::FieldDef, args: GenericArgsRef<'tcx>, ) -> FfiResult<'tcx> { @@ -1222,13 +1230,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { .tcx .try_normalize_erasing_regions(self.cx.param_env, field_ty) .unwrap_or(field_ty); - self.check_type_for_ffi(cache, field_ty) + self.check_type_for_ffi(acc, field_ty) } /// Checks if the given `VariantDef`'s field types are "ffi-safe". fn check_variant_for_ffi( &self, - cache: &mut FxHashSet>, + acc: &mut CTypesVisitorState<'tcx>, ty: Ty<'tcx>, def: ty::AdtDef<'tcx>, variant: &ty::VariantDef, @@ -1238,7 +1246,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let transparent_with_all_zst_fields = if def.repr().transparent() { if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { // Transparent newtypes have at most one non-ZST field which needs to be checked.. - match self.check_field_type_for_ffi(cache, field, args) { + match self.check_field_type_for_ffi(acc, field, args) { FfiUnsafe { ty, .. } if ty.is_unit() => (), r => return r, } @@ -1256,7 +1264,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // We can't completely trust `repr(C)` markings, so make sure the fields are actually safe. let mut all_phantom = !variant.fields.is_empty(); for field in &variant.fields { - all_phantom &= match self.check_field_type_for_ffi(cache, field, args) { + all_phantom &= match self.check_field_type_for_ffi(acc, field, args) { FfiSafe => false, // `()` fields are FFI-safe! FfiUnsafe { ty, .. } if ty.is_unit() => false, @@ -1276,7 +1284,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). - fn check_type_for_ffi(&self, cache: &mut FxHashSet>, ty: Ty<'tcx>) -> FfiResult<'tcx> { + fn check_type_for_ffi( + &self, + acc: &mut CTypesVisitorState<'tcx>, + ty: Ty<'tcx>, + ) -> FfiResult<'tcx> { use FfiResult::*; let tcx = self.cx.tcx; @@ -1285,7 +1297,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // `struct S(*mut S);`. // FIXME: A recursion limit is necessary as well, for irregular // recursive types. - if !cache.insert(ty) { + if !acc.cache.insert(ty) { return FfiSafe; } @@ -1307,6 +1319,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct | AdtKind::Union => { + if let Some(sym::cstring_type | sym::cstr_type) = + tcx.get_diagnostic_name(def.did()) + && !acc.base_ty.is_mutable_ptr() + { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_cstr_reason, + help: Some(fluent::lint_improper_ctypes_cstr_help), + }; + } + if !def.repr().c() && !def.repr().transparent() { return FfiUnsafe { ty, @@ -1353,7 +1376,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), args) + self.check_variant_for_ffi(acc, ty, def, def.non_enum_variant(), args) } AdtKind::Enum => { if def.variants().is_empty() { @@ -1377,7 +1400,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) { - return self.check_type_for_ffi(cache, ty); + return self.check_type_for_ffi(acc, ty); } return FfiUnsafe { @@ -1398,7 +1421,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - match self.check_variant_for_ffi(cache, ty, def, variant, args) { + match self.check_variant_for_ffi(acc, ty, def, variant, args) { FfiSafe => (), r => return r, } @@ -1468,9 +1491,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty), + ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(acc, ty), - ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty), + ty::Array(inner_ty, _) => self.check_type_for_ffi(acc, inner_ty), ty::FnPtr(sig) => { if self.is_internal_abi(sig.abi()) { @@ -1483,7 +1506,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = tcx.instantiate_bound_regions_with_erased(sig); for arg in sig.inputs() { - match self.check_type_for_ffi(cache, *arg) { + match self.check_type_for_ffi(acc, *arg) { FfiSafe => {} r => return r, } @@ -1494,7 +1517,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } - self.check_type_for_ffi(cache, ret_ty) + self.check_type_for_ffi(acc, ret_ty) } ty::Foreign(..) => FfiSafe, @@ -1617,7 +1640,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { + let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty }; + match self.check_type_for_ffi(&mut acc, ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { self.emit_ffi_unsafe_type_lint( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 94cf21da4efb8..407f95a0f21e3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -671,6 +671,7 @@ symbols! { crate_visibility_modifier, crt_dash_static: "crt-static", csky_target_feature, + cstr_type, cstring_type, ctlz, ctlz_nonzero, diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 22084dcff8f88..7808d42ab5de4 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -91,6 +91,7 @@ use crate::{fmt, intrinsics, ops, slice, str}; /// [str]: prim@str "str" #[derive(PartialEq, Eq, Hash)] #[stable(feature = "core_c_str", since = "1.64.0")] +#[rustc_diagnostic_item = "cstr_type"] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] // `fn from` in `impl From<&CStr> for Box` current implementation relies diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr index 8349298847918..044c1ae2dd42f 100644 --- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr @@ -1,21 +1,21 @@ -warning: `extern` fn uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` fn uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:7:12 | LL | type Foo = extern "C" fn(::std::ffi::CStr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes_definitions)]` on by default -warning: `extern` block uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` block uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:10:18 | LL | fn meh(blah: Foo); | ^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes)]` on by default warning: 2 warnings emitted diff --git a/tests/ui/lint/lint-ctypes-cstr.rs b/tests/ui/lint/lint-ctypes-cstr.rs new file mode 100644 index 0000000000000..b04decd0bcacc --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.rs @@ -0,0 +1,36 @@ +#![crate_type = "lib"] +#![deny(improper_ctypes, improper_ctypes_definitions)] + +use std::ffi::{CStr, CString}; + +extern "C" { + fn take_cstr(s: CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstr_ref(s: &CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring(s: CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring_ref(s: &CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + + fn no_special_help_for_mut_cstring(s: *mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + + fn no_special_help_for_mut_cstring_ref(s: &mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct +} + +extern "C" fn rust_take_cstr_ref(s: &CStr) {} +//~^ ERROR `extern` fn uses type `CStr`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_take_cstring(s: CString) {} +//~^ ERROR `extern` fn uses type `CString`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_no_special_help_for_mut_cstring(s: *mut CString) {} +extern "C" fn rust_no_special_help_for_mut_cstring_ref(s: &mut CString) {} diff --git a/tests/ui/lint/lint-ctypes-cstr.stderr b/tests/ui/lint/lint-ctypes-cstr.stderr new file mode 100644 index 0000000000000..8957758d57732 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.stderr @@ -0,0 +1,84 @@ +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:7:21 + | +LL | fn take_cstr(s: CStr); + | ^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:9 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:10:25 + | +LL | fn take_cstr_ref(s: &CStr); + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:13:24 + | +LL | fn take_cstring(s: CString); + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:16:28 + | +LL | fn take_cstring_ref(s: &CString); + | ^^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:20:43 + | +LL | fn no_special_help_for_mut_cstring(s: *mut CString); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:24:47 + | +LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` fn uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:29:37 + | +LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {} + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:26 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:32:36 + | +LL | extern "C" fn rust_take_cstring(s: CString) {} + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: aborting due to 8 previous errors + From f6767f7a68f42101e6820171c033565e0f3a807a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 31 Jul 2024 22:39:40 +0000 Subject: [PATCH 03/12] Detect `*` operator on `!Sized` expression ``` error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:15:9 | LL | let x = *""; | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | LL - let x = *""; LL + let x = ""; | ``` --- compiler/rustc_hir_typeck/src/expr.rs | 6 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 49 ++++++++++-- tests/ui/dst/dst-rvalue.stderr | 10 +++ tests/ui/issues/issue-17651.stderr | 5 ++ tests/ui/sized/unsized-binding.stderr | 5 ++ ...nsized-str-in-return-expr-arg-and-local.rs | 30 ++++++++ ...ed-str-in-return-expr-arg-and-local.stderr | 74 +++++++++++++++++++ .../suggestions/issue-84973-blacklist.stderr | 5 ++ tests/ui/unsized/unsized6.stderr | 10 +++ 10 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs create mode 100644 tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e54f9486f6a89..f13321a56bf7d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -841,6 +841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); let mut span = return_expr.span; + let mut hir_id = return_expr.hir_id; // Use the span of the trailing expression for our cause, // not the span of the entire function if !explicit_return @@ -848,6 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(last_expr) = body.expr { span = last_expr.span; + hir_id = last_expr.hir_id; } ret_coercion.borrow_mut().coerce( self, @@ -864,6 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.select_obligations_where_possible(|errors| { self.point_at_return_for_opaque_ty_error( errors, + hir_id, span, return_expr_ty, return_expr.span, @@ -921,6 +924,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn point_at_return_for_opaque_ty_error( &self, errors: &mut Vec>, + hir_id: HirId, span: Span, return_expr_ty: Ty<'tcx>, return_span: Span, @@ -935,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let new_cause = ObligationCause::new( cause.span, cause.body_id, - ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), + ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, hir_id))), ); *cause = new_cause; } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d54e2ca0a74f7..a3277fb96d229 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -353,7 +353,7 @@ pub enum ObligationCauseCode<'tcx> { ReturnValue(HirId), /// Opaque return type of this function - OpaqueReturnType(Option<(Ty<'tcx>, Span)>), + OpaqueReturnType(Option<(Ty<'tcx>, HirId)>), /// Block implicit return BlockTailExpression(HirId, hir::MatchSource), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 0d15ef55e24e7..b1aa455ce8860 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2725,6 +2725,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let tcx = self.tcx; let predicate = predicate.upcast(tcx); + let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| { + if let Some(pred) = predicate.as_trait_clause() + && tcx.is_lang_item(pred.def_id(), LangItem::Sized) + && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind + { + err.span_suggestion_verbose( + expr.span.until(inner.span), + "references are always `Sized`, even if they point to unsized data; consider \ + not dereferencing the expression", + String::new(), + Applicability::MaybeIncorrect, + ); + } + }; match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } @@ -2771,6 +2785,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) if !span.is_dummy() => { + if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code { + if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id) + && let hir::ExprKind::Call(_, args) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id) + && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } + } let item_name = tcx.def_path_str(item_def_id); let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id)); let mut multispan = MultiSpan::from(span); @@ -2968,6 +2995,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )); err.downgrade_to_delayed_bug(); } + let mut local = true; match tcx.parent_hir_node(hir_id) { Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => { err.span_suggestion_verbose( @@ -2976,7 +3004,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); } Node::LetStmt(hir::LetStmt { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), @@ -2991,7 +3018,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); + } + Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => { + // When encountering an assignment of an unsized trait, like `let x = *"";`, + // we check if the RHS is a deref operation, to suggest removing it. + suggest_remove_deref(err, &expr); } Node::Param(param) => { err.span_suggestion_verbose( @@ -3001,10 +3032,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); + local = false; } - _ => { - err.note("all local variables must have a statically known size"); - } + _ => {} + } + if local { + err.note("all local variables must have a statically known size"); } if !tcx.features().unsized_locals { err.help("unsized locals are gated as an unstable feature"); @@ -3527,14 +3560,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } ObligationCauseCode::OpaqueReturnType(expr_info) => { - if let Some((expr_ty, expr_span)) = expr_info { + if let Some((expr_ty, hir_id)) = expr_info { let expr_ty = self.tcx.short_ty_string(expr_ty, &mut long_ty_file); + let expr = self.infcx.tcx.hir().expect_expr(hir_id); err.span_label( - expr_span, + expr.span, with_forced_trimmed_paths!(format!( "return type was inferred to be `{expr_ty}` here", )), ); + suggest_remove_deref(err, &expr); } } } diff --git a/tests/ui/dst/dst-rvalue.stderr b/tests/ui/dst/dst-rvalue.stderr index 8d0a82b707dda..d8c529617f75f 100644 --- a/tests/ui/dst/dst-rvalue.stderr +++ b/tests/ui/dst/dst-rvalue.stderr @@ -9,6 +9,11 @@ LL | let _x: Box = Box::new(*"hello world"); = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box = Box::new(*"hello world"); +LL + let _x: Box = Box::new("hello world"); + | error[E0277]: the size for values of type `[isize]` cannot be known at compilation time --> $DIR/dst-rvalue.rs:8:37 @@ -21,6 +26,11 @@ LL | let _x: Box<[isize]> = Box::new(*array); = help: the trait `Sized` is not implemented for `[isize]` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box<[isize]> = Box::new(*array); +LL + let _x: Box<[isize]> = Box::new(array); + | error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/issues/issue-17651.stderr index 0c95a3c0c40d8..9519507320d82 100644 --- a/tests/ui/issues/issue-17651.stderr +++ b/tests/ui/issues/issue-17651.stderr @@ -9,6 +9,11 @@ LL | (|| Box::new(*(&[0][..])))(); = help: the trait `Sized` is not implemented for `[{integer}]` note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - (|| Box::new(*(&[0][..])))(); +LL + (|| Box::new((&[0][..])))(); + | error: aborting due to 1 previous error diff --git a/tests/ui/sized/unsized-binding.stderr b/tests/ui/sized/unsized-binding.stderr index 7c3276032c2b4..8de236cd0b6e0 100644 --- a/tests/ui/sized/unsized-binding.stderr +++ b/tests/ui/sized/unsized-binding.stderr @@ -7,6 +7,11 @@ LL | let x = *""; = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | error: aborting due to 1 previous error diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs new file mode 100644 index 0000000000000..35abbb80d99e5 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs @@ -0,0 +1,30 @@ +fn foo() -> impl Sized { +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` + *"" //~ HELP consider not dereferencing the expression +} +fn bar(_: impl Sized) {} +struct S; + +impl S { + fn baz(&self, _: impl Sized) {} +} + +fn main() { + let _ = foo(); + let x = *""; + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + //~| HELP unsized locals are gated as an unstable feature + bar(x); + S.baz(x); + bar(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + S.baz(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` +} diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr new file mode 100644 index 0000000000000..9b7258aff1261 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr @@ -0,0 +1,74 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:1:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | *"" + | --- return type was inferred to be `str` here + | + = help: the trait `Sized` is not implemented for `str` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - *"" +LL + "" + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:15:9 + | +LL | let x = *""; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:22:9 + | +LL | bar(*""); + | --- ^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `bar` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:6:16 + | +LL | fn bar(_: impl Sized) {} + | ^^^^^ required by this bound in `bar` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - bar(*""); +LL + bar(""); + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:26:11 + | +LL | S.baz(*""); + | --- ^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `S::baz` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:10:27 + | +LL | fn baz(&self, _: impl Sized) {} + | ^^^^^ required by this bound in `S::baz` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - S.baz(*""); +LL + S.baz(""); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index 4fd063e46926a..c1ef1cd428e4a 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -66,6 +66,11 @@ note: required by a bound in `f_sized` | LL | fn f_sized(t: T) {} | ^^^^^ required by this bound in `f_sized` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - f_sized(*ref_cl); +LL + f_sized(ref_cl); + | error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/issue-84973-blacklist.rs:27:12 diff --git a/tests/ui/unsized/unsized6.stderr b/tests/ui/unsized/unsized6.stderr index 56e7f60f9ff08..d406120efc532 100644 --- a/tests/ui/unsized/unsized6.stderr +++ b/tests/ui/unsized/unsized6.stderr @@ -123,6 +123,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3(x1: Box, x2: Box, x3: Box) { LL + fn f3(x1: Box, x2: Box, x3: Box) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 @@ -177,6 +182,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4(x1: Box, x2: Box, x3: Box) { LL + fn f4(x1: Box, x2: Box, x3: Box) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 From 4c5e888eb6846d4c777bd05cbc6af06a50faeb6a Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 22 Aug 2024 17:13:13 -0400 Subject: [PATCH 04/12] rustdoc: show exact case-sensitive matches first fixes #119480 --- src/librustdoc/html/static/js/search.js | 8 ++++++++ tests/rustdoc-js-std/exact-case.js | 7 +++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/rustdoc-js-std/exact-case.js diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 3eb27ea087c1d..63f492d5ac17e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1393,6 +1393,7 @@ function initSearch(rawSearchIndex) { */ async function sortResults(results, isType, preferredCrate) { const userQuery = parsedQuery.userQuery; + const casedUserQuery = parsedQuery.original; const result_list = []; for (const result of results.values()) { result.item = searchIndex[result.id]; @@ -1403,6 +1404,13 @@ function initSearch(rawSearchIndex) { result_list.sort((aaa, bbb) => { let a, b; + // sort by exact case-sensitive match + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } + // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); diff --git a/tests/rustdoc-js-std/exact-case.js b/tests/rustdoc-js-std/exact-case.js new file mode 100644 index 0000000000000..d9faff22fff70 --- /dev/null +++ b/tests/rustdoc-js-std/exact-case.js @@ -0,0 +1,7 @@ +const EXPECTED = { + 'query': 'Copy', + 'others': [ + { 'path': 'std::marker', 'name': 'Copy' }, + { 'path': 'std::fs', 'name': 'copy' }, + ], +} From b968b26c03510c80782c4524a334f5fa440cb2d8 Mon Sep 17 00:00:00 2001 From: Noa Date: Thu, 22 Aug 2024 14:42:24 -0500 Subject: [PATCH 05/12] Put Pin::as_deref_mut in impl Pin --- library/core/src/pin.rs | 121 ++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 0569b8b762433..1ad509892d26a 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1291,8 +1291,8 @@ impl Pin { /// // Now, if `x` was the only reference, we have a mutable reference to /// // data that we pinned above, which we could use to move it as we have /// // seen in the previous example. We have violated the pinning API contract. - /// } - /// ``` + /// } + /// ``` /// /// ## Pinning of closure captures /// @@ -1356,20 +1356,6 @@ impl Pin { Pin { __pointer: pointer } } - /// Gets a shared reference to the pinned value this [`Pin`] points to. - /// - /// This is a generic method to go from `&Pin>` to `Pin<&T>`. - /// It is safe because, as part of the contract of `Pin::new_unchecked`, - /// the pointee cannot move after `Pin>` got created. - /// "Malicious" implementations of `Pointer::Deref` are likewise - /// ruled out by the contract of `Pin::new_unchecked`. - #[stable(feature = "pin", since = "1.33.0")] - #[inline(always)] - pub fn as_ref(&self) -> Pin<&Ptr::Target> { - // SAFETY: see documentation on this function - unsafe { Pin::new_unchecked(&*self.__pointer) } - } - /// Unwraps this `Pin`, returning the underlying `Ptr`. /// /// # Safety @@ -1394,9 +1380,21 @@ impl Pin { pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { pin.__pointer } -} -impl Pin { + /// Gets a shared reference to the pinned value this [`Pin`] points to. + /// + /// This is a generic method to go from `&Pin>` to `Pin<&T>`. + /// It is safe because, as part of the contract of `Pin::new_unchecked`, + /// the pointee cannot move after `Pin>` got created. + /// "Malicious" implementations of `Pointer::Deref` are likewise + /// ruled out by the contract of `Pin::new_unchecked`. + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn as_ref(&self) -> Pin<&Ptr::Target> { + // SAFETY: see documentation on this function + unsafe { Pin::new_unchecked(&*self.__pointer) } + } + /// Gets a mutable reference to the pinned value this `Pin` points to. /// /// This is a generic method to go from `&mut Pin>` to `Pin<&mut T>`. @@ -1428,11 +1426,55 @@ impl Pin { /// ``` #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { + pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> + where + Ptr: DerefMut, + { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&mut *self.__pointer) } } + /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. + /// + /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is + /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot + /// move in the future, and this method does not enable the pointee to move. "Malicious" + /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of + /// `Pin::new_unchecked`. + #[unstable(feature = "pin_deref_mut", issue = "86918")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline(always)] + pub fn as_deref_mut(self: Pin<&mut Pin>) -> Pin<&mut Ptr::Target> + where + Ptr: DerefMut, + { + // SAFETY: What we're asserting here is that going from + // + // Pin<&mut Pin> + // + // to + // + // Pin<&mut Ptr::Target> + // + // is safe. + // + // We need to ensure that two things hold for that to be the case: + // + // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. + // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating + // `Pin<&mut Pin>` + // + // The existence of `Pin` is sufficient to guarantee #1: since we already have a + // `Pin`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that `Ptr` is _also_ pinned. + // + // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the + // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains + // any access to the `Ptr` itself, much less the `Pin`. + unsafe { self.get_unchecked_mut() }.as_mut() + } + /// Assigns a new value to the memory location pointed to by the `Pin`. /// /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets @@ -1457,6 +1499,7 @@ impl Pin { #[inline(always)] pub fn set(&mut self, value: Ptr::Target) where + Ptr: DerefMut, Ptr::Target: Sized, { *(self.__pointer) = value; @@ -1613,46 +1656,6 @@ impl Pin<&'static T> { } } -impl<'a, Ptr: DerefMut> Pin<&'a mut Pin> { - /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. - /// - /// This is a generic method to go from `Pin<&mut Pin>>` to `Pin<&mut T>`. It is - /// safe because the existence of a `Pin>` ensures that the pointee, `T`, cannot - /// move in the future, and this method does not enable the pointee to move. "Malicious" - /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of - /// `Pin::new_unchecked`. - #[unstable(feature = "pin_deref_mut", issue = "86918")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline(always)] - pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> { - // SAFETY: What we're asserting here is that going from - // - // Pin<&mut Pin> - // - // to - // - // Pin<&mut Ptr::Target> - // - // is safe. - // - // We need to ensure that two things hold for that to be the case: - // - // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. - // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating - // `Pin<&mut Pin>` - // - // The existence of `Pin` is sufficient to guarantee #1: since we already have a - // `Pin`, it must already uphold the pinning guarantees, which must mean that - // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely - // on the fact that `Ptr` is _also_ pinned. - // - // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the - // `Pin` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains - // any access to the `Ptr` itself, much less the `Pin`. - unsafe { self.get_unchecked_mut() }.as_mut() - } -} - impl Pin<&'static mut T> { /// Gets a pinning mutable reference from a static mutable reference. /// From c65ef3d37c312dc0404da8b5c3f781d376778aad Mon Sep 17 00:00:00 2001 From: Noa Date: Fri, 23 Aug 2024 13:06:26 -0500 Subject: [PATCH 06/12] Move into_inner_unchecked back to the bottom of the impl block --- library/core/src/pin.rs | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 1ad509892d26a..0f9e6061c32da 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1356,31 +1356,6 @@ impl Pin { Pin { __pointer: pointer } } - /// Unwraps this `Pin`, returning the underlying `Ptr`. - /// - /// # Safety - /// - /// This function is unsafe. You must guarantee that you will continue to - /// treat the pointer `Ptr` as pinned after you call this function, so that - /// the invariants on the `Pin` type can be upheld. If the code using the - /// resulting `Ptr` does not continue to maintain the pinning invariants that - /// is a violation of the API contract and may lead to undefined behavior in - /// later (safe) operations. - /// - /// Note that you must be able to guarantee that the data pointed to by `Ptr` - /// will be treated as pinned all the way until its `drop` handler is complete! - /// - /// *For more information, see the [`pin` module docs][self]* - /// - /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used - /// instead. - #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] - #[stable(feature = "pin_into_inner", since = "1.39.0")] - pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { - pin.__pointer - } - /// Gets a shared reference to the pinned value this [`Pin`] points to. /// /// This is a generic method to go from `&Pin>` to `Pin<&T>`. @@ -1504,6 +1479,31 @@ impl Pin { { *(self.__pointer) = value; } + + /// Unwraps this `Pin`, returning the underlying `Ptr`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will continue to + /// treat the pointer `Ptr` as pinned after you call this function, so that + /// the invariants on the `Pin` type can be upheld. If the code using the + /// resulting `Ptr` does not continue to maintain the pinning invariants that + /// is a violation of the API contract and may lead to undefined behavior in + /// later (safe) operations. + /// + /// Note that you must be able to guarantee that the data pointed to by `Ptr` + /// will be treated as pinned all the way until its `drop` handler is complete! + /// + /// *For more information, see the [`pin` module docs][self]* + /// + /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used + /// instead. + #[inline(always)] + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] + pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { + pin.__pointer + } } impl<'a, T: ?Sized> Pin<&'a T> { From 62f7d5305e2f702fae205105dffb22447c5b1e6d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 12:02:26 -0700 Subject: [PATCH 07/12] Update `compiler_builtins` to `0.1.121` --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index f2f446b61085d..aa22181a4639a 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.120" +version = "0.1.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c44e9c76d996d8049dee591a997eab801069ad86ed892ed3039f68b73d301c" +checksum = "ce956e6dc07082ec481f0935a51e83b343f8ca51be560452c0ebf830d0bdf5a5" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 43799acc02736..a39a0a6ce0ea2 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.120", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.121", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index dca42a3e98ec1..334c75df2315a 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.120" } +compiler_builtins = { version = "0.1.121" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ From 5c6285c5f07a7cb47eff6efe90a9dc20634c3b2d Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Fri, 23 Aug 2024 19:16:01 +0000 Subject: [PATCH 08/12] Add myself to the review rotation for libs --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 9bb1befb69983..d7bc60e6c6f09 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -951,6 +951,7 @@ libs = [ "@joboet", "@jhpratt", "@tgross35", + "@thomcc", ] bootstrap = [ "@Mark-Simulacrum", From 5cef88c1f492beff80d6694b118ea7526c135185 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 22 Aug 2024 21:07:29 +0000 Subject: [PATCH 09/12] Print the generic parameter along with the variance in dumps. --- .../rustc_hir_analysis/src/variance/dump.rs | 32 ++++++++++++++----- tests/ui/error-codes/E0208.rs | 2 +- tests/ui/error-codes/E0208.stderr | 2 +- .../impl-trait/capture-lifetime-not-in-hir.rs | 4 +-- .../capture-lifetime-not-in-hir.stderr | 4 +-- .../impl-trait/implicit-capture-late.stderr | 2 +- tests/ui/impl-trait/in-trait/variance.rs | 12 ++++--- tests/ui/impl-trait/in-trait/variance.stderr | 12 +++---- tests/ui/impl-trait/variance.e2024.stderr | 8 ++--- tests/ui/impl-trait/variance.new.stderr | 8 ++--- tests/ui/impl-trait/variance.old.stderr | 6 ++-- tests/ui/impl-trait/variance.rs | 14 ++++---- tests/ui/type-alias-impl-trait/variance.rs | 32 +++++++++---------- .../ui/type-alias-impl-trait/variance.stderr | 32 +++++++++---------- .../ui/variance/variance-associated-consts.rs | 2 +- .../variance-associated-consts.stderr | 2 +- .../ui/variance/variance-associated-types.rs | 4 +-- .../variance/variance-associated-types.stderr | 4 +-- tests/ui/variance/variance-object-types.rs | 2 +- .../ui/variance/variance-object-types.stderr | 2 +- tests/ui/variance/variance-regions-direct.rs | 14 ++++---- .../variance/variance-regions-direct.stderr | 14 ++++---- .../ui/variance/variance-regions-indirect.rs | 10 +++--- .../variance/variance-regions-indirect.stderr | 10 +++--- tests/ui/variance/variance-trait-bounds.rs | 8 ++--- .../ui/variance/variance-trait-bounds.stderr | 8 ++--- .../variance/variance-trait-object-bound.rs | 2 +- .../variance-trait-object-bound.stderr | 2 +- tests/ui/variance/variance-types-bounds.rs | 10 +++--- .../ui/variance/variance-types-bounds.stderr | 10 +++--- tests/ui/variance/variance-types.rs | 12 +++---- tests/ui/variance/variance-types.stderr | 12 +++---- 32 files changed, 158 insertions(+), 140 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 1a17dabb677ac..ace183986bd00 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -1,18 +1,36 @@ +use std::fmt::Write; + use rustc_hir::def::DefKind; -use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::ty::TyCtxt; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_middle::ty::{GenericArgs, TyCtxt}; use rustc_span::symbol::sym; +fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { + let variances = tcx.variances_of(def_id); + let generics = GenericArgs::identity_for_item(tcx, def_id); + // 7 = 2-letter parameter + ": " + 1-letter variance + ", " + let mut ret = String::with_capacity(2 + 7 * variances.len()); + ret.push('['); + for (arg, variance) in generics.iter().zip(variances.iter()) { + write!(ret, "{arg}: {variance:?}, ").unwrap(); + } + // Remove trailing `, `. + if !variances.is_empty() { + ret.pop(); + ret.pop(); + } + ret.push(']'); + ret +} + pub(crate) fn variances(tcx: TyCtxt<'_>) { if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue }; - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } @@ -22,11 +40,9 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) { continue; } - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs index 74c138af483c1..2713ba6ed6cb5 100644 --- a/tests/ui/error-codes/E0208.rs +++ b/tests/ui/error-codes/E0208.rs @@ -1,7 +1,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct Foo<'a, T> { //~ ERROR [+, o] +struct Foo<'a, T> { //~ ERROR ['a: +, T: o] t: &'a mut T, } diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr index 77b6ceae4dcee..a39e93afab3e1 100644 --- a/tests/ui/error-codes/E0208.stderr +++ b/tests/ui/error-codes/E0208.stderr @@ -1,4 +1,4 @@ -error: [+, o] +error: ['a: +, T: o] --> $DIR/E0208.rs:4:1 | LL | struct Foo<'a, T> { diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs index 9c067cb693444..2fde0f200c0e5 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -6,13 +6,13 @@ trait Bar<'a> { } fn foo<'a, T: Bar<'a>>() -> impl Into { - //~^ ERROR [o, o] + //~^ ERROR ['a: o, T: o] // captures both T and 'a invariantly () } fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { - //~^ ERROR [o, o, o] + //~^ ERROR ['a: o, T: o, 'a: o] // captures both T and 'a invariantly, and also duplicates `'a` // i.e. the opaque looks like `impl Into<>::Assoc> + 'a_duplicated` () diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr index 9d52001b02460..fe8a2772a00b1 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -1,10 +1,10 @@ -error: [o, o] +error: ['a: o, T: o] --> $DIR/capture-lifetime-not-in-hir.rs:8:29 | LL | fn foo<'a, T: Bar<'a>>() -> impl Into { | ^^^^^^^^^^^^^^^^^^^ -error: [o, o, o] +error: ['a: o, T: o, 'a: o] --> $DIR/capture-lifetime-not-in-hir.rs:14:30 | LL | fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr index 080750f849767..3adf78322d2e5 100644 --- a/tests/ui/impl-trait/implicit-capture-late.stderr +++ b/tests/ui/impl-trait/implicit-capture-late.stderr @@ -10,7 +10,7 @@ note: lifetime declared here LL | fn foo(x: Vec) -> Box Deref> { | ^^ -error: [o] +error: ['a: o] --> $DIR/implicit-capture-late.rs:10:55 | LL | fn foo(x: Vec) -> Box Deref> { diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 65565dcc2a6f4..0ac44bf7546c2 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -7,14 +7,16 @@ impl Captures<'_> for T {} trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [o, *, *, o, o] - // Self, 'i, 'a, 'i_duplicated, 'a_duplicated + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [o, *, *, o, o] + fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} //~ [o, *, o, o] + fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o, *, o, o] + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 8cae5a92f0dd5..54e0afbaa950d 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,23 +1,23 @@ -error: [o, *, *, o, o] +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:9:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, *, o, o] - --> $DIR/variance.rs:13:44 +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:12:44 | LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, *, o, o] +error: [Self: o, 'i: *, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, o, o] - --> $DIR/variance.rs:17:48 +error: [Self: o, 'i: *, 'a: o, 'i: o] + --> $DIR/variance.rs:18:48 | LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr index 1724505574413..011ab3259c477 100644 --- a/tests/ui/impl-trait/variance.e2024.stderr +++ b/tests/ui/impl-trait/variance.e2024.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr index 1724505574413..011ab3259c477 100644 --- a/tests/ui/impl-trait/variance.new.stderr +++ b/tests/ui/impl-trait/variance.new.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr index 9410b54b491a8..ac3bcd2723fb3 100644 --- a/tests/ui/impl-trait/variance.old.stderr +++ b/tests/ui/impl-trait/variance.old.stderr @@ -1,10 +1,10 @@ -error: [*] +error: ['a: *] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} @@ -16,7 +16,7 @@ error: [] LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index 72b4a831badcb..43f7207a90423 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -12,17 +12,17 @@ trait Captures<'a> {} impl Captures<'_> for T {} fn not_captured_early<'a: 'a>() -> impl Sized {} -//[old]~^ [*] -//[new]~^^ [*, o] -//[e2024]~^^^ [*, o] +//[old]~^ ['a: *] +//[new]~^^ ['a: *, 'a: o] +//[e2024]~^^^ ['a: *, 'a: o] -fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [*, o] +fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ['a: *, 'a: o] fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} //[old]~^ [] -//[new]~^^ [o] -//[e2024]~^^^ [o] +//[new]~^^ ['a: o] +//[e2024]~^^^ ['a: o] -fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o] +fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ['a: o] fn main() {} diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index ba52eaa035971..113f6a4cc4491 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -5,21 +5,21 @@ trait Captures<'a> {} impl Captures<'_> for T {} -type NotCapturedEarly<'a> = impl Sized; //~ [*, o] +type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o] +type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ [*, o, o] +type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Captured<'a> = dyn for<'b> Iterator>; //~ [*, o, o] +type Captured<'a> = dyn for<'b> Iterator>; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o] +type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR ['a: *, 'b: *, T: o, 'a: o, 'b: o] //~^ ERROR: unconstrained opaque type trait Foo<'i> { @@ -31,24 +31,24 @@ trait Foo<'i> { } impl<'i> Foo<'i> for &'i () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } @@ -59,15 +59,15 @@ impl<'a> Nesting<'a> for &'a () { type Output = &'a (); } type NestedDeeply<'a> = - impl Nesting< //~ [*, o] + impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting<'a> //~ [*, o] + Output = impl Nesting<'a> //~ ['a: *, 'a: o] > >, >, diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index e5ced7a498171..489dfe03d446c 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -110,73 +110,73 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:8:29 | LL | type NotCapturedEarly<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:11:26 | LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:14:56 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; | ^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:18:49 | LL | type Captured<'a> = dyn for<'b> Iterator>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o, o] +error: ['a: *, 'b: *, T: o, 'a: o, 'b: o] --> $DIR/variance.rs:22:27 | LL | type Bar<'a, 'b: 'b, T> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:34:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:37:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:40:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:45:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:48:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:51:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:62:5 | LL | / impl Nesting< @@ -188,7 +188,7 @@ LL | | >, LL | | >; | |_____^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:64:18 | LL | Output = impl Nesting< @@ -201,7 +201,7 @@ LL | | >, LL | | >, | |_________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:66:22 | LL | Output = impl Nesting< @@ -214,7 +214,7 @@ LL | | > LL | | >, | |_____________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:68:26 | LL | Output = impl Nesting< @@ -224,7 +224,7 @@ LL | | Output = impl Nesting<'a> LL | | > | |_________________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:70:30 | LL | Output = impl Nesting<'a> diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs index 6a44a94df3fdd..97edb7e266ad0 100644 --- a/tests/ui/variance/variance-associated-consts.rs +++ b/tests/ui/variance/variance-associated-consts.rs @@ -10,7 +10,7 @@ trait Trait { } #[rustc_variance] -struct Foo { //~ ERROR [o] +struct Foo { //~ ERROR [T: o] field: [u8; ::Const] //~^ ERROR: unconstrained generic constant } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index b955a7686c2a7..5c3ed93464ac6 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -9,7 +9,7 @@ help: try adding a `where` bound LL | struct Foo where [(); ::Const]: { | ++++++++++++++++++++++++++++++++ -error: [o] +error: [T: o] --> $DIR/variance-associated-consts.rs:13:1 | LL | struct Foo { diff --git a/tests/ui/variance/variance-associated-types.rs b/tests/ui/variance/variance-associated-types.rs index ecb0821827dc0..07ff41062e881 100644 --- a/tests/ui/variance/variance-associated-types.rs +++ b/tests/ui/variance/variance-associated-types.rs @@ -10,12 +10,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR [+, +] +struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +] field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR [o, o] +struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o] field: >::Type } diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr index 70cb246f6e906..ca010b7e7ef40 100644 --- a/tests/ui/variance/variance-associated-types.stderr +++ b/tests/ui/variance/variance-associated-types.stderr @@ -1,10 +1,10 @@ -error: [+, +] +error: ['a: +, T: +] --> $DIR/variance-associated-types.rs:13:1 | LL | struct Foo<'a, T : Trait<'a>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: ['a: o, T: o] --> $DIR/variance-associated-types.rs:18:1 | LL | struct Bar<'a, T : Trait<'a>> { diff --git a/tests/ui/variance/variance-object-types.rs b/tests/ui/variance/variance-object-types.rs index 6ded24cd1e9ed..fd03dec982492 100644 --- a/tests/ui/variance/variance-object-types.rs +++ b/tests/ui/variance/variance-object-types.rs @@ -4,7 +4,7 @@ // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR [o] +struct Foo<'a> { //~ ERROR ['a: o] x: Box &'a i32 + 'static> } diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr index 963f3454e1baf..a6fb9b2403a6b 100644 --- a/tests/ui/variance/variance-object-types.stderr +++ b/tests/ui/variance/variance-object-types.stderr @@ -1,4 +1,4 @@ -error: [o] +error: ['a: o] --> $DIR/variance-object-types.rs:7:1 | LL | struct Foo<'a> { diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index f1763c403f1a1..2bcacec33ea5a 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -6,7 +6,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] +struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +] x: &'a isize, y: &'b [isize], c: &'c str @@ -15,7 +15,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] +struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -24,7 +24,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR [+, o] +struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut &'b isize, } @@ -32,7 +32,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR [+, o] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR [-, o] +struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o] x: extern "Rust" fn(&'a mut &'b isize), } @@ -42,14 +42,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR [-, o] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR [+, o] +struct Test6<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR [*] +struct Test7<'a> { //~ ERROR ['a: *] //~^ ERROR: `'a` is never used x: isize } @@ -57,7 +57,7 @@ struct Test7<'a> { //~ ERROR [*] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR [-, +, o] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index edfc888f65667..45ce0303fb251 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -6,43 +6,43 @@ LL | struct Test7<'a> { | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error: [+, +, +] +error: ['a: +, 'b: +, 'c: +] --> $DIR/variance-regions-direct.rs:9:1 | LL | struct Test2<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, -, -] +error: ['a: -, 'b: -, 'c: -] --> $DIR/variance-regions-direct.rs:18:1 | LL | struct Test3<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:27:1 | LL | struct Test4<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, o] +error: ['a: -, 'b: o] --> $DIR/variance-regions-direct.rs:35:1 | LL | struct Test5<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:45:1 | LL | struct Test6<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [*] +error: ['a: *] --> $DIR/variance-regions-direct.rs:52:1 | LL | struct Test7<'a> { | ^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-direct.rs:60:1 | LL | enum Test8<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 31e25641d8c3a..aaa4d3f877995 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *] //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -13,25 +13,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR ['w: *, 'x: o, 'y: +, 'z: -] //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR ['a: o, 'b: o, 'c: *] //~^ ERROR: `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR ['a: o, 'b: +, 'c: *] //~^ ERROR: `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [-, +, o] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] f: Base<'a, 'b, 'c, 'a> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index 901ec0c6a762b..ed839b3235009 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -30,31 +30,31 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` -error: [-, +, o, *] +error: ['a: -, 'b: +, 'c: o, 'd: *] --> $DIR/variance-regions-indirect.rs:8:1 | LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, +, -] +error: ['w: *, 'x: o, 'y: +, 'z: -] --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o, *] +error: ['a: o, 'b: o, 'c: *] --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, +, *] +error: ['a: o, 'b: +, 'c: *] --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-indirect.rs:34:1 | LL | struct Derived4<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index 25a01b160ddd1..f86fa2bbef7a0 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -13,24 +13,24 @@ trait Setter { } #[rustc_variance] -struct TestStruct> { //~ ERROR [+, +] +struct TestStruct> { //~ ERROR [U: +, T: +] t: T, u: U } #[rustc_variance] -enum TestEnum> { //~ ERROR [*, +] +enum TestEnum> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] -struct TestContraStruct> { //~ ERROR [*, +] +struct TestContraStruct> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR [*, +] +struct TestBox+Setter> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 95ed18c1ad2bf..49cee3cbeca75 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -25,25 +25,25 @@ LL | struct TestBox+Setter> { = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead -error: [+, +] +error: [U: +, T: +] --> $DIR/variance-trait-bounds.rs:16:1 | LL | struct TestStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:21:1 | LL | enum TestEnum> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox+Setter> { diff --git a/tests/ui/variance/variance-trait-object-bound.rs b/tests/ui/variance/variance-trait-object-bound.rs index 11303c4652005..ca80c6b6dce22 100644 --- a/tests/ui/variance/variance-trait-object-bound.rs +++ b/tests/ui/variance/variance-trait-object-bound.rs @@ -11,7 +11,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR [+] +struct TOption<'a> { //~ ERROR ['a: +] v: Option>, } diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr index f0471a3461925..0af21ec12cc9b 100644 --- a/tests/ui/variance/variance-trait-object-bound.stderr +++ b/tests/ui/variance/variance-trait-object-bound.stderr @@ -1,4 +1,4 @@ -error: [+] +error: ['a: +] --> $DIR/variance-trait-object-bound.rs:14:1 | LL | struct TOption<'a> { diff --git a/tests/ui/variance/variance-types-bounds.rs b/tests/ui/variance/variance-types-bounds.rs index d1814dd97a0ad..f4738a2dae1ab 100644 --- a/tests/ui/variance/variance-types-bounds.rs +++ b/tests/ui/variance/variance-types-bounds.rs @@ -4,24 +4,24 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR [+, +] +struct TestImm { //~ ERROR [A: +, B: +] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR [+, o] +struct TestMut { //~ ERROR [A: +, B: o] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR [+, o] +struct TestIndirect { //~ ERROR [A: +, B: o] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR [o, o] +struct TestIndirect2 { //~ ERROR [A: o, B: o] n: TestMut, m: TestMut } @@ -35,7 +35,7 @@ trait Setter { } #[rustc_variance] -struct TestObject { //~ ERROR [o, o] +struct TestObject { //~ ERROR [A: o, R: o] n: Box+Send>, m: Box+Send>, } diff --git a/tests/ui/variance/variance-types-bounds.stderr b/tests/ui/variance/variance-types-bounds.stderr index bb81644347693..408c2ae8d3682 100644 --- a/tests/ui/variance/variance-types-bounds.stderr +++ b/tests/ui/variance/variance-types-bounds.stderr @@ -1,28 +1,28 @@ -error: [+, +] +error: [A: +, B: +] --> $DIR/variance-types-bounds.rs:7:1 | LL | struct TestImm { | ^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:13:1 | LL | struct TestMut { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:19:1 | LL | struct TestIndirect { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, B: o] --> $DIR/variance-types-bounds.rs:24:1 | LL | struct TestIndirect2 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, R: o] --> $DIR/variance-types-bounds.rs:38:1 | LL | struct TestObject { diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs index cfc03b754734d..aa336d1b424c1 100644 --- a/tests/ui/variance/variance-types.rs +++ b/tests/ui/variance/variance-types.rs @@ -7,32 +7,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [+, o, o] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR [o] +struct InvariantCell { //~ ERROR [A: o] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR [o] +struct InvariantIndirect { //~ ERROR [A: o] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR [+] +struct Covariant { //~ ERROR [A: +] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR [-] +struct Contravariant { //~ ERROR [A: -] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR [+, -, o] +enum Enum { //~ ERROR [A: +, B: -, C: o] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr index 0fda4b8036e72..f2a6794942553 100644 --- a/tests/ui/variance/variance-types.stderr +++ b/tests/ui/variance/variance-types.stderr @@ -1,34 +1,34 @@ -error: [+, o, o] +error: ['a: +, A: o, B: o] --> $DIR/variance-types.rs:10:1 | LL | struct InvariantMut<'a,A:'a,B:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:15:1 | LL | struct InvariantCell { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:20:1 | LL | struct InvariantIndirect { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+] +error: [A: +] --> $DIR/variance-types.rs:25:1 | LL | struct Covariant { | ^^^^^^^^^^^^^^^^^^^ -error: [-] +error: [A: -] --> $DIR/variance-types.rs:30:1 | LL | struct Contravariant { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, -, o] +error: [A: +, B: -, C: o] --> $DIR/variance-types.rs:35:1 | LL | enum Enum { From 32e34eef576e0fb54cab52e7ba32abe028200377 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 24 Aug 2024 03:11:00 +0200 Subject: [PATCH 10/12] make text more easy to read --- .../rustc/src/platform-support/wasm32-unknown-unknown.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index ee37e5e90cfb4..dde915f316948 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -29,10 +29,10 @@ that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web. ## Target maintainers -When this target was added to the compiler platform-specific documentation here +When this target was added to the compiler, platform-specific documentation here was not maintained at that time. This means that the list below is not -exhaustive and there are more interested parties in this target. That being -said since when this document was last updated those interested in maintaining +exhaustive, and there are more interested parties in this target. That being +said, when this document was last updated, those interested in maintaining this target are: - Alex Crichton, https://github.com/alexcrichton From f734f3d8e73f2118fdf4bdaf35e72ace8a442531 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 24 Aug 2024 05:40:27 +0200 Subject: [PATCH 11/12] remove extraneous text --- src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index dde915f316948..12b7817c38277 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -32,8 +32,7 @@ that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web. When this target was added to the compiler, platform-specific documentation here was not maintained at that time. This means that the list below is not exhaustive, and there are more interested parties in this target. That being -said, when this document was last updated, those interested in maintaining -this target are: +said, those interested in maintaining this target are: - Alex Crichton, https://github.com/alexcrichton From 027c47983ee161f3346e6be39c14cfc33d03e169 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 24 Aug 2024 12:35:35 -0400 Subject: [PATCH 12/12] update the doc comment on lintchecker b/c it parses html now --- src/tools/linkchecker/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 72448c1180a97..fa77ab1e011cd 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -6,8 +6,10 @@ //! script is to check all relative links in our documentation to make sure they //! actually point to a valid place. //! -//! Currently this doesn't actually do any HTML parsing or anything fancy like -//! that, it just has a simple "regex" to search for `href` and `id` tags. +//! Currently uses a combination of HTML parsing to +//! extract the `href` and `id` attributes, +//! and regex search on the orignal markdown to handle intra-doc links. +//! //! These values are then translated to file URLs if possible and then the //! destination is asserted to exist. //!